title: How to use Volatile properly so that writes get flushed to main memory?
body: <p>Below is an example from a book</p>
  <pre><code>internal sealed class ThreadsSharingData {    
      private Int32 m_flag = 0;
      private Int32 m_value = 0;
      // This method is executed by one thread
      public void Thread1() {        
          m_value = 5;
          m_flag = 1;        
      }
  
      // This method is executed by another thread
      public void Thread2() {        
          // Note: m_value must be read after m_flag is read
          if (m_flag == 1)
          Console.WriteLine(m_value);        
      }    
  }
  </code></pre>
  <p>The author says:</p>
  <blockquote>
  <p>The problem with this code is that the compilers/CPU could translate the code in such a way as to
  reverse the two lines of code in the Thread1 method. After all, reversing the two lines of code does not change the intention of the method. The method needs to get a 5 in m_value and a 1 in m_flag. From a single-threaded application’s perspective, the order of executing this code is unimportant. If these two lines do execute in reverse order, then another thread executing the Thread2 method could see that m_flag is 1 and then display 0.</p>
  </blockquote>
  <blockquote>
  <p>Let's look at this code another way. Let's say that the code in the Thread1 method executes in
  program order (the way it was written). When compiling the code in the Thread2 method, the compiler must generate code to read m_flag and m_value from RAM into CPU registers. It is possible
  that RAM will deliver the value of m_value first, which would contain a 0. Then the Thread1 method
  could execute, changing m_value to 5 and m_flag to 1. But Thread2’s CPU register doesn’t see that
  m_value has been changed to 5 by this other thread, and then the value in m_flag could be read
  from RAM into a CPU register and the value of m_flag becomes 1 now, causing Thread2 to again display 0.</p>
  </blockquote>
  <p>The author says <code>Volatile</code> class can fix the problem as:</p>
  <pre><code>internal sealed class ThreadsSharingData {    
      private Int32 m_flag = 0;
      private Int32 m_value = 0;
      // This method is executed by one thread
      public void Thread1() {        
          // Note: 5 must be written to m_value before 1 is written to m_flag
          m_value = 5;
          Volatile.Write(ref m_flag, 1);        
      }
  
      // This method is executed by another thread
      public void Thread2() {        
          // Note: m_value must be read after m_flag is read
          if (Volatile.Read(ref m_flag) == 1)
          Console.WriteLine(m_value);        
      }    
  }
  </code></pre>
  <p>But I have a question, when we uses <code>Volatile.Write(ref m_flag, 1);</code>, it means:</p>
  <ol>
  <li><code>m_value = 5</code> is before the call to Volatile.Write, it must complete first</li>
  <li><code>m_flag</code>'s latest value (which is 1) is flushed to main memory immmediately so that Thread2 can see this latest value</li>
  </ol>
  <p>But &quot;<code>m_value = 5</code> is before the call to Volatile.Write&quot; just mean the register that holds <code>m_value</code> is 5, which might not flushed to the main memory yet, so thread2 might still display 0. I don't think <code>Volatile.Write</code> can make any writes statments before it get updated to main memory too, <code>Volatile.Write</code> just disables reorder. so isn't the correct way to do is:</p>
  <pre><code>internal sealed class ThreadsSharingData {    
      private Int32 m_flag = 0;
      private Int32 m_value = 0;
      public void Thread1() {        
         Volatile.Write(ref m_value, 5);   // make sure m_value's latest value flushed to main memory
         Volatile.Write(ref m_flag, 1);        
      }
  
      public void Thread2() {        
          // Note: m_value must be read after m_flag is read
          if (Volatile.Read(ref m_flag) == 1
          Console.WriteLine(Volatile.Read(ref m_value));  // read m_value's latest value from main memory    
      }    
  }
  </code></pre>