title: .Net memory visibility behavior
body: <p>EDIT: I've finally written a complete article about the issue: <strong><a href="http://pragmateek.com/synchronization-memory-visibility-and-leaky-abstractions/" rel="nofollow" title="Synchronization, memory visibility and leaky abstractions">Synchronization, memory visibility and leaky abstractions</a></strong></p>
  
  <hr>
  
  <p>I'm demonstrating the importance of <strong>volatile read</strong> with this code:</p>
  
  <pre><code>bool ok = false;
  
  void F()
  {
      int n = 0;
      while (!ok) ++n;
  }
  
  public void Run()
  {
      Thread thread = new Thread(F);
      thread.Start();
  
      Console.Write("Press enter to notify thread...");
      Console.ReadLine();
  
      ok = true;
  
      Console.WriteLine("Thread notified.");
  }
  </code></pre>
  
  <p>As expected the thread is not aware of the new <code>ok</code> value and the program hangs.</p>
  
  <p>But to obtain this behavior I have to do something in the <code>while</code> loop, e.g. incrementing an integer.</p>
  
  <p>If I remove the <code>++n</code> statement, the thread reads the new value and exits.</p>
  
  <p>I guess it has something to do with the <strong>JITter optimizations</strong> because as far as CIL is concerned there is nothing (at least for a layman like me):</p>
  
  <pre><code>.method private hidebysig instance void  F() cil managed
  {
    .maxstack  2
    .locals init ([0] int32 n)
    IL_0000:  ldc.i4.0
    IL_0001:  stloc.0
    IL_0002:  br.s       IL_0008
    IL_0004:  ldloc.0
    IL_0005:  ldc.i4.1
    IL_0006:  add
    IL_0007:  stloc.0
    IL_0008:  ldarg.0
    IL_0009:  ldfld      bool ThreadingSamples.MemoryVisibilitySample::ok
    IL_000e:  brfalse.s  IL_0004
    IL_0010:  ret
  }
  
  
  .method private hidebysig instance void  F() cil managed
  {
    .maxstack  8
    IL_0000:  ldarg.0
    IL_0001:  ldfld      bool ThreadingSamples.MemoryVisibilitySample::ok
    IL_0006:  brfalse.s  IL_0000
    IL_0008:  ret
  }
  </code></pre>
  
  <p>And, on the contrary, I would naively expect that doing something in the loop would increase the odds for the thread to trigger a cache refresh.</p>
  
  <p>What am I missing again?</p>
  
  <hr>
  
  <p>FINAL EDIT: this is again some <strong>JITter</strong> black-magic.</p>
  
  <p>Kudos to Hans for confirming this is a "well-known" JITter "issue" and for pointing out that in <strong>x64</strong> we get the "expected" behavior.</p>
  
  <p>Kudos to <em>MagnatLU</em> for providing the resulting assembly code and for sharing some debugging wisdom.</p>