58

是否有系统的方法可以知道 C# 中的操作是否是原子的?或者是否有任何一般的指导方针或经验法则?

4

3 回答 3

41

对于更完整/详细的内容:

对 32 位值类型的读取和写入是原子的:这包括以下内在值 (struct) 类型:bool, char, byte, sbyte, short, ushort, int, uint, float. 以下类型(其中包括)不保证是原子的:decimal, double, long, ulong.

例如

int x;
x = 10; // atomic
decimal d;

d = 10m; // not atomic

引用赋值也是一个原子操作:

private String _text;
public void Method(String text)
{
  _text = text; // atomic
}
于 2012-07-31T17:25:30.377 回答
33

是的。阅读 CLI 规范: http: //www.ecma-international.org/publications/standards/Ecma-335.htm。例如:

I.12.6.6 原子读写

符合 CLI 的 CLI 应保证对正确对齐的内存位置的读写访问不大于本机字大小(本机 int 类型的大小)是原子的(参见 §I.12.6.2)相同的大小。原子写入不应改变除已写入的位之外的任何位。除非使用显式布局控制(参见分区 II(控制实例布局))来更改默认行为,否则不大于自然字大小(本机 int 的大小)的数据元素应正确对齐。对象引用应被视为以本机字长存储。

[注意:不能保证内存的原子更新(读-修改-写),除了作为类库的一部分为此目的提供的方法(参见第 IV 部分)。在不支持直接写入小数据项的硬件上进行原子读/修改/写需要“小数据项”(不大于本机字大小的项)的原子写入。尾注]

[注意:当本机 int 的大小为 32 位时,不能保证对 8 字节数据的原子访问,即使某些实现可能在数据在 8 字节边界上对齐时执行原子操作。尾注]

关于 64 位长的问题,Eric Lippert 在这里回答:https ://ericlippert.com/2011/05/31/atomicity-volatility-and-immutability-are-different-part-two/

CLI 规范实际上提供了更强的保证。CLI 保证对处理器自然指针大小(或更小)的值类型变量的读取和写入是原子的;如果您在 64 位版本的 CLR 中在 64 位操作系统上运行 C# 代码,那么 64 位双精度和长整数的读写也保证是原子的。C# 语言不保证这一点,但运行时规范可以。(如果您在某些 CLI 实现未实现的环境中运行 C# 代码,那么您当然不能依赖该保证;如果您想知道他们提供什么保证,请联系向您出售运行时的供应商。)

关于原子访问的另一个微妙点是,底层处理器仅在被读取或写入的变量与与内存中正确位置对齐的存储相关联时才保证原子性。最终,该变量将作为指向某处内存的指针来实现。在 32 位操作系统上,该指针必须能被 4 整除才能保证读取或写入是原子的,而在 64 位操作系统上,它必须能被 8 整除。

于 2012-07-31T17:11:32.637 回答
8

从 CLI 规范中,您可以在此处获取:

“符合标准的 CLI 应保证对正确对齐的内存位置的读写访问不大于本机字大小(本机 int 类型的大小)是原子的……”</p>

C# 规范的第 12.5 节在这里

“以下数据类型的读取和写入应是原子的:bool、char、byte、sbyte、short、ushort、uint、int、float 和引用类型。” 另外:“……不保证原子读取-修改-写入,例如在递增或递减的情况下。”</p>

使用this使增量操作成为原子操作。

于 2012-07-31T17:20:00.177 回答