title: Is memory_order_acquire really sufficient for locking a spinlock?
body: <p>According to Antony Williams' book <em>C++ Concurrency in Action</em> a spinlock can be implemented as follows:</p>
  
  <pre><code>class spinlock_mutex {
    std::atomic_flag flag;
  
  public:
    spinlock_mutex() : flag(ATOMIC_FLAG_INIT) {}
  
    void lock() {
      while (flag.test_and_set(std::memory_order_acquire)) ;
    }
  
    void unlock() {
     flag.clear(std::memory_order_release);
    }
  };
  </code></pre>
  
  <p>If I understand correctly, the <code>memory_order_acquire</code> tag ensures visibility of the most recent store operation that used the <code>memory_order_release</code> tag. ("A release operation <em>synchronizes-with</em> an acquire operation.")</p>
  
  <p>Since <code>test_and_set</code> is also a store operation I would expect that a <code>memory_order_acq_rel</code> tag is required inside the <code>lock()</code> method in order to ensure visibility of the locked state in other threads that attempt to lock the mutex.</p>
  
  <p>Why is <code>memory_order_acquire</code> sufficient?</p>