C#中的原子操作是什么?

C#中的原子操作是什么?,c#,.net,multithreading,atomic,C#,.net,Multithreading,Atomic,有没有一种系统的方法可以知道C#中的一个操作是否是原子的?或者有什么一般的指导原则或经验法则吗?有。请阅读CLI规范:。例如: I.12.6.6原子读写 符合要求的CLI应保证对 正确对齐的内存位置不大于本机字大小 (本机int类型的大小)是原子的(见§I.12.6.2),当所有 对位置的写入访问大小相同。原子写入应 除了写下的内容外,不要改变其他内容。除非有明确的布局 控件(请参阅分区II(控制实例布局))用于 改变默认行为,数据元素不大于自然值 字号(本机整数的大小)应正确对齐。 对象引用应

有没有一种系统的方法可以知道C#中的一个操作是否是原子的?或者有什么一般的指导原则或经验法则吗?

有。请阅读CLI规范:。例如:

I.12.6.6原子读写

符合要求的CLI应保证对 正确对齐的内存位置不大于本机字大小 (本机int类型的大小)是原子的(见§I.12.6.2),当所有 对位置的写入访问大小相同。原子写入应 除了写下的内容外,不要改变其他内容。除非有明确的布局 控件(请参阅分区II(控制实例布局))用于 改变默认行为,数据元素不大于自然值 字号(本机整数的大小)应正确对齐。 对象引用应被视为存储在 本机字号

[注:不保证原子更新 (读-修改-写)内存,但为此提供的方法除外 作为类库的一部分的用途(参见分区IV)。原子 写入“小数据项”(不大于本机单词的项) 在以下硬件上执行原子读取/修改/写入时需要 不支持直接写入小数据项。结束说明]

[注: 当 本机int为32位,即使某些实现可能会执行 当数据在8字节边界上对齐时的原子操作。结束 注]

关于64位长的问题,Eric Lippert回答如下:

CLI规范实际上提供了更有力的保证。CLI 保证读取和写入值类型为 处理器的自然指针大小(或更小)为 原子的;如果您在64位操作系统上以 然后,64位版本的CLR读取和写入64位双精度和双精度 长整数也保证是原子的。C语言确实如此 不能保证,但运行时规范可以。(如果您运行的是C# 某些环境中的代码,这些代码不是由某些 当然,CLI的实现不能依赖于此 保证;如果愿意,请联系向您出售运行时的供应商 了解他们提供的担保。)

原子访问的另一个微妙之处是 处理器仅在读取或删除变量时保证原子性 写入与向右对齐的存储相关联 内存中的位置。最终,该变量将作为 指向某处内存的指针。在32位操作系统上 指针必须能被4整除才能进行读写操作 保证是原子的,并且在64位操作系统上 可以被8整除


从CLI规范中,您可以获得:

“符合要求的CLI应保证对 正确对齐的内存位置不大于本机字大小 (类型native int的大小)是原子的…”

C#规范第12.5节:

“以下数据类型的读写应为原子型:bool, char、byte、sbyte、short、ushort、uint、int、float和reference 类型。此外:“…不保证原子读修改写, 例如在递增或递减的情况下。”


使增量操作原子化。

以获取更完整/详细的信息:

对32位值类型的读写是原子的:这包括以下内在值(结构)类型:
bool、char、byte、sbyte、short、ushort、int、uint、float
。以下类型(以及其他类型)不保证是原子的:
decimal、double、long、ulong

e、 g

引用分配也是一种原子操作:

private String _text;
public void Method(String text)
{
  _text = text; // atomic
}

除了联锁类之外,该类具有原子增量、减量和其他几个。不完全正确-如果系统的本机字大小为64位(例如运行64位版本windows的x64处理器),则64位值(长)也是原子的甚至在64位应用程序上引用也是原子的吗?@C#spec中的Chrishain:“其他类型的读写,包括long、ulong、double和decimal,以及用户定义的类型,都不能保证是原子的。“@PeterRitchie C#spec说不能保证long是原子的,但它绝不禁止原子性。我的理解是,在64位CLI上,它们是原子的,这是因为我在回答中发布的CLI spec部分中有保证。也就是说,如果这方面的权威可以说其他的话,我愿意被证明是错误的明智的是,为什么在64位平台上访问
long
会是非原子的。@克丽莎因你是对的,规范没有说它们是“非”原子或“从不”原子的,我已经澄清了我的答案(这并不是说它们永远不会是原子的,只是不能保证)。但是,您必须为x64编译以确保它是。如果不为x64编译,代码可能在x86中运行,因此不是原子的;因此,您必须假设它不是原子的,并使用lock或Monitor.Enter/Exit来确保它是以原子方式访问的。Eric确实说“C语言不能保证这一点。“w.r.t.64位值和原子性。。。只有在一个特定的CLI下才有这种可能性。迂腐的;但是OP没有指定哪个客户端。。。
private String _text;
public void Method(String text)
{
  _text = text; // atomic
}