问题
I recently learnt here the following is thread-safe on x86 CPU with the x86 CLR (not necessarily ECMA standard CLR)
public class SometimesThreadSafe
{
private int value;
public int Value { get { return value; } }
public void Update()
{
Interlocked.Add(ref value, 47);
}
}
This is because writing to an int on such architectures ensures any other CPU caches of value are synched. On ARM CPUs however this is not thread safe! As reading value from a different thread could read an old copy from a CPU cache.
So the question is on what CPU architectures and with what versions of the CLR and it's variants, e.g. Mono, is this thread-safe?
回答1:
"Thread-safe" isn't exactly the proper word to apply to this kind of code. The access to the Value property getter is completely unsynchronized with the Update() method so the value you get is entirely unpredictable. Including never seeing the update.
The only concern you have here if the Value property getter is atomic. In other words, if you'll ever be able to observe a partially updated value of the property where some bytes will have been changed by Update() and some not. This is guaranteed by the CLI spec. Ecma-335, section I.12.6.6, "Atomic reads and writes":
A conforming CLI shall guarantee that read and write access to properly aligned memory locations no larger than the native word size (the size of type native int) is atomic (see §I.12.6.2) when all the write accesses to a location are the same size. Atomic writes shall alter no bits other than those written. Unless explicit layout control (see Partition II (Controlling Instance Layout)) is used to alter the default behavior, data elements no larger than the natural word size (the size of a native int) shall be properly aligned. Object references shall be treated as though they are stored in the native word size.
This guarantee is toned down somewhat in the C# Language Specification, chapter 5.5, "Atomicity of variable references". It avoids taking a dependency on the size of IntPtr:
Reads and writes of the following data types are atomic: bool, char, byte, sbyte, short, ushort, uint, int, float, and reference types. In addition, reads and writes of enum types with an underlying type in the previous list are also atomic. Reads and writes of other types, including long, ulong, double, and decimal, as well as user-defined types, are not guaranteed to be atomic.
Anyhoo, not a problem for int on any architecture.
If thread-safety is truly your concern then this code is just plain wrong. It is not thread-safe on any architecture. The notion of "implicitly volatile" doesn't exist in the .NET memory model. Something the x86 jitter optimizer takes advantage of, it will store the backing field of the property in a cpu register and not update it from memory. You'll never observe the update. Explicitly declaring it volatile is required to suppress this optimization.
来源:https://stackoverflow.com/questions/20345756/on-which-cpu-architectures-are-writes-to-an-int-implicitly-volatile-using-the