title: Is there a race condition in this common pattern used to prevent NullReferenceException?
body: <p>I asked <strong><a href="https://stackoverflow.com/q/10565838/651789">this</a></strong> question and got <strong><a href="https://stackoverflow.com/a/10567171/651789">this</a></strong> interesting (and a little disconcerting) answer.</p>
  
  <p>Daniel states in his answer (unless I'm reading it incorrectly) that the <strong>ECMA-335 CLI</strong> specification could allow a compiler to generate code that throws a <code>NullReferenceException</code> from the following <code>DoCallback</code> method.</p>
  
  <pre><code>class MyClass {
      private Action _Callback;
      public Action Callback { 
          get { return _Callback; }
          set { _Callback = value; }
      }
      public void DoCallback() {
          Action local;
          local = Callback;
          if (local == null)
              local = new Action(() =&gt; { });
          local();
      }
  }
  </code></pre>
  
  <p>He says that, in order to guarantee a <code>NullReferenceException</code> is not thrown, the <code>volatile</code> keyword should be used on <code>_Callback</code> or a <code>lock</code> should be used around the line <code>local = Callback;</code>.</p>
  
  <p>Can anyone corroborate that? And, if it's true, is there a difference in behavior between <strong>Mono</strong> and <strong>.NET</strong> compilers regarding this issue?</p>
  
  <p><strong>Edit</strong><br />
  Here is a link to the <strong><a href="http://www.ecma-international.org/publications/standards/Ecma-335.htm" rel="nofollow noreferrer">standard</a></strong>.</p>
  
  <p><strong>Update</strong><br />
  I think this is the pertinent part of the spec (12.6.4):</p>
  
  <blockquote>
    <p>Conforming implementations of the CLI are free to execute programs
    using any technology that guarantees, within a single thread of
    execution, that side-effects and exceptions generated by a thread are
    visible in the order specified by the CIL. For this purpose only
    volatile operations (including volatile reads) constitute visible
    side-effects. (Note that while only volatile operations constitute
    visible side-effects, volatile operations also affect the visibility
    of non-volatile references.) Volatile operations are specified in
    §12.6.7. There are no ordering guarantees relative to exceptions
    injected into a thread by another thread (such exceptions are
    sometimes called "asynchronous exceptions" (e.g.,
    System.Threading.ThreadAbortException). </p>
    
    <p>[Rationale: An optimizing
    compiler is free to reorder side-effects and synchronous exceptions to
    the extent that this reordering does not change any observable program
    behavior. end rationale] </p>
    
    <p>[Note: An implementation of the CLI is
    permitted to use an optimizing compiler, for example, to convert CIL
    to native machine code provided the compiler maintains (within each
    single thread of execution) the same order of side-effects and
    synchronous exceptions.</p>
  </blockquote>
  
  <p>So... I'm curious as to whether or not this statement allows a compiler to optimize the <code>Callback</code> property (which accesses a simple field) and the <code>local</code> variable to produce the following, which has the same behavior <strong>in a single thread of execution</strong>:</p>
  
  <pre><code>if (_Callback != null) _Callback();
  else new Action(() =&gt; { })();
  </code></pre>
  
  <p>The 12.6.7 section on the <code>volatile</code> keyword seems to offer a solution for programmers wishing to avoid the optimization:</p>
  
  <blockquote>
    <p>A volatile read has "acquire semantics" meaning that the read is
    guaranteed to occur prior to any references to memory that occur after
    the read instruction in the CIL instruction sequence. A volatile write
    has "release semantics" meaning that the write is guaranteed to happen
    after any memory references prior to the write instruction in the CIL
    instruction sequence. A conforming implementation of the CLI shall
    guarantee this semantics of volatile operations. This ensures that all
    threads will observe volatile writes performed by any other thread in
    the order they were performed. But a conforming implementation is not
    required to provide a single total ordering of volatile writes as seen
    from all threads of execution. An optimizing compiler that converts
    CIL to native code shall not remove any volatile operation, nor shall
    it coalesce multiple volatile operations into a single operation.</p>
  </blockquote>