title: What are the exact inter-thread reordering constraints on mutex.lock() and .unlock() in c++11 and up?
body: <p>According to <a href="https://en.cppreference.com/w/cpp/atomic/memory_order" rel="nofollow noreferrer">https://en.cppreference.com/w/cpp/atomic/memory_order</a> <code>mutex.lock()</code> and <code>mutex.unlock()</code> are acquire and release operations. An acquire operation makes it impossible to reorder later instructions in front of it. And release operations make it impossible to reorder earlier instructions after it. This makes it such that the following code:</p>
  <pre><code>[Thread 1]
  mutex1.lock();
  mutex1.unlock();
  mutex2.lock();
  mutex2.unlock();
  [Thread 2]
  mutex2.lock();
  mutex2.unlock();
  mutex1.lock();
  mutex1.unlock();
  </code></pre>
  <p>Can be reordered into the following (possibly deadlocking) code:</p>
  <pre><code>[Thread 1]
  mutex1.lock();
  mutex2.lock();
  mutex1.unlock();
  mutex2.unlock();
  [Thread 2]
  mutex2.lock();
  mutex1.lock();
  mutex2.unlock();
  mutex1.unlock();
  </code></pre>
  <p>Is it possible for this reordering to occur. Or is there a rule preventing it?</p>