When the background thread sets true to a member variable, there is a fence, and the value is written to memory, and the other processor cache is updated or cleared from this address.
Calling the Console.WriteLine function is a fence of full memory, and its semantics, perhaps something (without compiler optimization) will require stop not be cached.
However, if you delete the Console.WriteLine call, I find that the function is still stopping.
I believe that the compiler, in the absence of optimizations, the compiler does not cache anything computed from global memory. The volatile keyword is an instruction not to even think about caching any expression that includes this variable in the / JIT compiler.
This code still stops (at least for me, I use Mono):
public void Start() { stop = false; var thread = new Thread(() => { while(true) { Thread.Sleep(50); stop = !stop; } }); thread.Start(); while ( !(stop ^ stop) ); }
This shows that this is not a while statement that prevents caching, since it shows that the variable is not cached even within the same expression.
This optimization looks sensitive to a memory model, which is platform dependent, which would be done in a JIT compiler; which would not have time (or intelligence) to / see / use the variable in another thread and prevent caching for this reason.
Perhaps Microsoft does not believe that programmers can know when to use volatile and decide to strip them of responsibility, and then Mono followed suit.
source share