title: Barriers and synchronization points with non-atomic variables - data race?
body: <p>Consider the following program:</p>
  <pre><code>int                        i{0};
  std::experimental::barrier b{2};
  
  int main()
  {
      std::thread t0{[] {
          b.arrive_and_wait();
          std::cout &lt;&lt; i &lt;&lt; '\n';
      }};
  
      std::thread t1{[] {
          i = 2;
          b.arrive_and_wait();
      }};
  
      t0.join();
      t1.join();
  }
  </code></pre>
  <p><strong>Is this program guaranteed to print out <code>2</code>, even though <code>i</code> is not an atomic variable?</strong></p>
  <p>According to <a href="https://en.cppreference.com/w/cpp/experimental/barrier/arrive_and_wait" rel="noreferrer">cppreference</a>:</p>
  <blockquote>
  <p>Calls to <code>arrive_and_wait</code> synchronizes with the start of the completion phase of the barrier. The completion of the completion phase synchronizes with the return from the call.</p>
  <p>Calls to <code>arrive_and_drop</code> and <code>arrive_and_wait</code> never introduce data races with themselves or each other.</p>
  </blockquote>
  <p>This suggests that there is a synchronization point on each <code>arrive_and_wait</code> call. However I am not sure if the compiler is allowed to reorder the read/write operations on <code>i</code>, since it is non-atomic.</p>