Is memory_order_acquire really sufficient for locking a spinlock?
atomic, c++
Solution
The acquire and release are related not to this atomic variable, but to the rest of variables read/written in each one of the threads.
To make it more obvious, without the release in `unlock()` and the acquire in the `lock()` the flag would still be visible. The problem is that a write to a variable protected by the spin lock may be pushed after the lock is released, introducing a race condition. In the same way a read of that variable inside the lock might be moved to before the `lock()`
Problem
According to Antony Williams' book C++ Concurrency in Action a spinlock can be implemented as follows: ``` 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); } }; ``` If I understand correctly, the `memory_order_acquire` tag ensures visibility of the most recent store operation that used the `memory_order_release` tag. ("A release operation synchronizes-with an acquire operation.") Since `test_and_set` is also a store operation I would expect that a `memory_order_acq_rel` tag is required inside the `lock()` method in order to ensure visibility of the locked state in other threads that attempt to lock the mutex. Why is `memory_order_acquire` sufficient?