使用CLR(和变体)将哪些CPU体系结构写入int“隐式易失性”?

我最近在这里学到以下是x86 CPU上的线程安全x86 CLR(不一定是ECMA标准CLR)

public class SometimesThreadSafe { private int value; public int Value { get { return value; } } public void Update() { Interlocked.Add(ref value, 47); } } 

这是因为在此类体系结构上写入int可确保同步任何其他CPU缓存。 但是在ARM CPU上,这不是线程安全的! 从另一个线程读取值可以读取CPU缓存中的旧副本。

所以问题在于CPU体系结构以及CLR的哪些版本及其变体(例如Mono)是否具有线程安全性?

“线程安全”并不是适用于这种代码的正确词。 对Value属性getter的访问与Update()方法完全不同步,因此您获得的值完全不可预测。 包括从未见过更新。

如果Value属性getter是primefaces的,那么你唯一关心的就是这里。 换句话说,如果你能够观察到属性的部分更新值,其中某些字节将被Update()更改而某些字节不会被更改。 这是CLI规范保证的。 Ecma-335,第I.12.6.6节,“primefaces读写”:

符合标准的CLI应保证对一个位置的所有写访问都是primefaces的(见§I.12.6.2),对正确对齐的内存位置的读写访问不大于本机字大小(native int类型的大小)。大小相同。 primefaces写入除了写入之外不得改变任何位。 除非使用显式布局控件(请参阅分区II(控制实例布局))来更改默认行为,否则应正确对齐不大于自然字大小(本机int的大小)的数据元素。 对象引用应被视为存储在本机字大小中。

在C#语言规范第5.5章“变量引用的primefaces性”中,这种保证有所降低。 它避免依赖于IntPtr的大小:

以下数据类型的读取和写入是primefaces的:bool,char,byte,sbyte,short,ushort,uint,int,float和reference类型。 此外,在先前列表中具有基础类型的枚举类型的读取和写入也是primefaces的。 其他类型的读写,包括long,ulong,double和decimal,以及用户定义的类型,不保证是primefaces的。

Anyhoo,在任何架构上都不是int的问题。

如果确实是线程安全问题,那么这段代码就是完全错误的。 它在任何架构上都不是线程安全的。 .NET内存模型中不存在“隐式易变”的概念。 x86 jitter优化器利用的东西,它会将属性的支持字段存储在cpu寄存器中,而不是从内存中更新它。 你永远不会看到更新。 必须明确声明它是不稳定的,以抑制此优化。