title: Acquire/release semantics with 4 threads
body: <p>I am currently reading C++ Concurrency in Action by Anthony Williams. One of his listing shows this code, and he states that the assertion that <code>z != 0</code> can fire. </p>
  
  <pre><code>#include &lt;atomic&gt;
  #include &lt;thread&gt;
  #include &lt;assert.h&gt;
  
  std::atomic&lt;bool&gt; x,y;
  std::atomic&lt;int&gt; z;
  
  void write_x()
  {
      x.store(true,std::memory_order_release);
  }
  
  void write_y()
  {
      y.store(true,std::memory_order_release);
  }
  
  void read_x_then_y()
  {
      while(!x.load(std::memory_order_acquire));
      if(y.load(std::memory_order_acquire))
          ++z;
  }
  
  void read_y_then_x()
  {
      while(!y.load(std::memory_order_acquire));
      if(x.load(std::memory_order_acquire))
          ++z;
  }
  
  int main()
  {
      x=false;
      y=false;
      z=0;
      std::thread a(write_x);
      std::thread b(write_y);
      std::thread c(read_x_then_y);
      std::thread d(read_y_then_x);
      a.join();
      b.join();
      c.join();
      d.join();
      assert(z.load()!=0);
  }
  </code></pre>
  
  <p>So the different execution paths, that I can think of is this:</p>
  
  <p>1)</p>
  
  <blockquote>
  <pre><code>Thread a (x is now true)
  Thread c (fails to increment z)
  Thread b (y is now true)
  Thread d (increments z) assertion cannot fire
  </code></pre>
  </blockquote>
  
  <p>2)</p>
  
  <blockquote>
  <pre><code>Thread b (y is now true)
  Thread d (fails to increment z)
  Thread a (x is now true)
  Thread c (increments z) assertion cannot fire
  </code></pre>
  </blockquote>
  
  <p>3)</p>
  
  <blockquote>
  <pre><code>Thread a (x is true)
  Thread b (y is true)
  Thread c (z is incremented) assertion cannot fire
  Thread d (z is incremented)
  </code></pre>
  </blockquote>
  
  <p>Could someone explain to me how this assertion can fire? </p>
  
  <p>He shows this little graphic:
  <a href="https://i.stack.imgur.com/roFkv.png" rel="noreferrer"><img src="https://i.stack.imgur.com/roFkv.png" alt="Image"></a></p>
  
  <p>Shouldn't the store to <code>y</code> also sync with the load in <code>read_x_then_y</code>, and the store to <code>x</code> sync with the load in <code>read_y_then_x</code>? I'm very confused. </p>
  
  <p>EDIT:</p>
  
  <p>Thank you for your responses, I understand how atomics work and how to use Acquire/Release. I just don't get this specific example. I was trying to figure out IF the assertion fires, then what did each thread do? And why does the assertion never fire if we use sequential consistency. </p>
  
  <p>The way, I am reasoning about this is that if <code>thread a</code> (<code>write_x</code>) stores to <code>x</code> then all the work it has done so far is synced with any other thread that reads <code>x</code> with acquire ordering. Once <code>read_x_then_y</code> sees this, it breaks out of the loop and reads <code>y</code>. Now, 2 things could happen. In one option, the <code>write_y</code> has written to <code>y</code>, meaning this release will sync with the if statement (load) meaning <code>z</code> is incremented and assertion cannot fire. The other option is if <code>write_y</code> hasn't run yet, meaning the if condition fails and z isn't incremented, In this scenario, only <code>x</code> is true and <code>y</code> is still false. Once write_y runs, the read_y_then_x breaks out of its loop, however both <code>x</code> and <code>y</code> are true and <code>z</code> is incremented and the assertion does not fire. I can't think of any 'run' or memory ordering where <code>z</code> is never incremented. Can someone explain where my reasoning is flawed?</p>
  
  <p>Also, I know The loop read will always be before the if statement read because the acquire prevents this reordering. </p>