I was looking at list 5.13 in C++ Concurrency in Action by Antony Williams:, and I am confused by the comments "the store to and load from y still have to be atomic; otherwise, there would be a data race on y". That implies that if y is a normal (non-atomic) bool then the assert may fire, but why?
#include <atomic>
#include <thread>
#include <assert.h>
bool x=false; 
std::atomic<bool> y;
std::atomic<int> z;
void write_x_then_y()
{
 x=true; 
 std::atomic_thread_fence(std::memory_order_release);
 y.store(true,std::memory_order_relaxed); 
}
void read_y_then_x()
{
 while(!y.load(std::memory_order_relaxed)); 
 std::atomic_thread_fence(std::memory_order_acquire);
 if(x) ++z;
}
int main()
{
 x=false;
 y=false;
 z=0;
 std::thread a(write_x_then_y);
 std::thread b(read_y_then_x);
 a.join();
 b.join();
 assert(z.load()!=0); 
}
Now let's change y to a normal bool, and I want to understand why the assert can fire.
#include <atomic>
#include <thread>
#include <assert.h>
bool x=false; 
bool y=false;
std::atomic<int> z;
void write_x_then_y()
{
 x=true; 
 std::atomic_thread_fence(std::memory_order_release);
 y=true;
}
void read_y_then_x()
{
 while(!y); 
 std::atomic_thread_fence(std::memory_order_acquire);
 if(x) ++z;
}
int main()
{
 x=false;
 y=false;
 z=0;
 std::thread a(write_x_then_y);
 std::thread b(read_y_then_x);
 a.join();
 b.join();
 assert(z.load()!=0); 
}
I understand that a data race happens on non-atomic global variables, but in this example if the while loop in read_y_then_x exits, my understanding is that y must either already be set to true, or in the process of being set to true (because it is a non-atomic operation) in the write_x_then_y thread. Since atomic_thread_fence in the write_x_then_y thread makes sure no code written above that can be reordered after, I think the x=true operation must have been finished. In addition, the std::memory_order_release and std::memory_order_acquire tags in two threads make sure that the updated value of x has been synchronized-with the read_y_then_x thread when reading x, so I feel the assert still holds... What am I missing?
 
     
    