The following code is a race condition:
#include#include #include using namespace std; int main(int argc, char** argv) { atomic_bool flag{false}; bool data{false}; thread t1([&]() { data = true; flag.store(true, memory_order_relaxed); }); thread t2([&]() { while(flag.load(memory_order_relaxed) == false); cout << "data = " << boolalpha << data << endl; }); t1.join(); t2.join(); return 1; }
Because
memory_order_relaxedis used the compiler and the CPU are free to reorder the two writes in thread
t1. They are also free to reorder the two reads in thread
t2. Hence undefined behavior.
The fix is to either use
memory_order_seq_cston the
storeand
loadcalls, or
memory_order_releaseon the
storecall and
memory_order_acquireon the load call. Release prevents any prior loads and stores to be reordered past it; acquire guarantees that all stores from the thread that released the atomic variable are visible to the current thread; it also prevents reads and writes to be reordered before it. See here.