Search code examples
c++c++11memory-model

Strange results about C++11 memory model (Relaxed ordering)


I was testing the example in the memory model of the Anthony Williams's book "C++ Concurrency"

#include<atomic>
#include<thread>
#include<cassert>

std::atomic_bool x,y;
std::atomic_int z;

void write_x_then_y() {
  x.store(true, std::memory_order_relaxed);
  y.store(true, std::memory_order_relaxed);
}

void read_y_then_x() {
  while(!y.load(std::memory_order_relaxed));
  if(x.load(std::memory_order_relaxed)) {
    ++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);
}

According to the explanation, relaxed operations on difference variables (here x and y) can be freely reordered. However, I repeated running the problem for more than several days. I never hit the situation that the assertion (assert(z.load()!=0);) fires. I just use the default optimization and compile the code using g++ -std=c++11 -lpthread dataRaceAtomic.cpp Does anyone actually try it and hit the assertion? Could anyone give me an explanation about my test results? BTW, I also tried the version without using the atomic type, I got the same result. Currently, both programs are running healthily. Thanks.


Solution

  • This can depend on the type of processor you are running on.

    x86 does not have a memory model as relaxed as other processors. In particular, stores will never be reordered with regards to other stores.

    http://bartoszmilewski.com/2008/11/05/who-ordered-memory-fences-on-an-x86/ has more info on x86's memory model.