I have read the threading manual and relevant MSDN pages and SO questions several times. Still, I do not completely understand if Volatile.Read/Write and interlocked operations apply only to the relevant variables, or all read/writes before/after that operations.
E.g., imagine I have an array and a counter.
long counter = 0;
var values = new double;
values = 3.1415;
// Is this line needed instead of simple assignment above,
// or the implicit full-fence of Interlocked will guarantee that
// all threads will see the values after interlocked increment?
//Volatile.Write(ref values, 3.1415);
Volatile.Write(ref values, 3.1415);
values = 3.1415;
If the variables protected are references to heap objects, you need to worry about using the read protection each time you touch a field. Just like locks, this technique doesn’t compose. As with anything other than simple locking, use this technique with great care and caution; although the built-in acquire and release fences shield you from memory model reordering issues, there are some easy traps you can fall into.
What you are probably missing is an understanding of fences. This is the best resource to read up on them: http://www.albahari.com/threading/part4.aspx
The short answer is
Interlocked.Increment issues a full fence which is independent of the variable it is updating. I believe
Volatile.Write issues a half fence. A half fence can be constructed from
Thread.MemoryBarrier. When we say
Interlocked.Increment issues a full fence it means that
Thread.MemoryBarrier is called before and after the operation.
Thread.MemoryBarrier before the write and
Volatile.Read after. The fences determine when memory access can be reordered (and it's not variable specific as
Thread.MemoryBarrier is parameterless).