Basically I have the following situation:
var tmp1 = new MyObject() { A = i, B = 2 };
// ** write barrier here??
this.Obj = tmp1;
Another thread can do stuff like this:
var tmp = this.Obj;
// ** read barrier here??
use(tmp.A);
Objects like 'Obj' are only written once, then read by multiple threads (multiple times).
I know that Obj is never null in both threads; I also don't care about the synchronization of 'this.Obj'. What I do care about is that once I read the reference tmp = Obj
, the contents (e.g. A
and B
) are also valid.
My question is: Do I need memory barriers (e.g. Thread.MemoryBarrier();
) at the above marked positions to ensure that or is this always implicitly OK?
It seems that people dislike this question.
My question originates from the following. I've read up on memory fences and they guarantee: (quote)
The processor executing the current thread cannot reorder instructions in such a way that memory accesses prior to the call to MemoryBarrier execute after memory accesses that follow the call to MemoryBarrier.
If you look at the code, the CPU / compiler might be able to re-write the code:
var tmp1 = new MyObject();
tmp1.A = i;
tmp1.B = 2;
this.Obj = tmp1;
and worse:
var tmp1 = new MyObject();
this.Obj = tmp1;
tmp1.A = i;
tmp1.B = 2;
If another thread picks up the last case, it can read this.Obj
from memory, while A
and B
still have the default value.
Note that it's not just a matter of what the compiler is able to reorder; it's also a matter of what the CPU is allowed to reorder.
In other words: (Thanks @MattBurland )
Is it guaranteed that the object initializer will be run before tmp1 is assigned to this.Obj
? Or do I need to use a memory fence to ensure this manually?