As per the C# specs, is there any guarantee that foo.Bar
would have the same effect of being atomic (i.e. reading foo.Bar
from different threads would never see a partially updated struct when written to by different threads)?
I've always assumed that it does. If indeed, I would like to know if the specification guarantees it.
public class Foo<T> where T : struct
{
private object bar;
public T Bar
{
get { return (T) bar; }
set { bar = value; }
}
}
// var foo = new Foo<Baz>();
EDIT: @vesan This is not the duplicate of Atomic Assignment of Reference Sized Structs. This question asks for the effect of boxing and unboxing whereas the other is about a single reference type in a struct (no boxing / unboxing involved). The only similarities between the two questions are the words struct and atomic (did you actually read the question at all?).
EDIT2: Here's the atomic version based on Raymond Chen's answer:
public class Atomic<T> where T : struct
{
private object m_Value = default(T);
public T Value
{
get { return (T) m_Value; }
set { Thread.VolatileWrite(ref m_Value, value); }
}
}
EDIT3: Revisiting this after 4 years. Turns out that the memory model of CLR2.0+ states that All writes have the effect of volatile write
: https://blogs.msdn.microsoft.com/pedram/2007/12/28/clr-2-0-memory-model/
Thus the answer to this question should have been "It is atomic if hardware does not reorder writes", as opposed to Raymond's answer. The JIT and the compiler cannot reorder writes so the "atomic version" based on Raymond's answer is redundant. On weak memory model architectures, the hardware may reorder writes, so you'll need to appropriate acquire/release semantics.
EDIT4: Again, this issue comes down to CLR vs CLI (ECMA) where the latter defines a very weak memory model while the former implements a strong memory model. There's no guarantee that a runtime will do this though, so the answer still stands. However, since the vast majority of code was and still is written for CLR, I suspect anyone trying to create a new runtime will take the easier path and implement strong memory model at the detriment of performance (just my own opinion).