How do memory_order_seq_cst and memory_order_acq_rel differ?

c++, c++11, memory-model, stdatomic

Solution

http://en.cppreference.com/w/cpp/atomic/memory_order has a good example at the bottom that only works with `memory_order_seq_cst`. Essentially `memory_order_acq_rel` provides read and write orderings relative to the atomic variable, while `memory_order_seq_cst` provides read and write ordering globally. That is, the sequentially consistent operations are visible in the same order across all threads.

The example boils down to this:

bool x= false;
bool y= false;
int z= 0;

a() { x= true; }
b() { y= true; }
c() { while (!x); if (y) z++; }
d() { while (!y); if (x) z++; }

// kick off a, b, c, d, join all threads
assert(z!=0);

Operations on `z` are guarded by two atomic variables, not one, so you can't use acquire-release semantics to enforce that `z` is always incremented.

Problem

Stores are release operations and loads are acquire operations for both. I know that `memory_order_seq_cst` is meant to impose an additional total ordering for all operations, but I'm failing to build an example where it isn't the case if all the `memory_order_seq_cst` are replaced by `memory_order_acq_rel`. Do I miss something, or the difference is just a documentation effect, i.e. one should use `memory_order_seq_cst` if one intend not to play with a more relaxed model and use `memory_order_acq_rel` when constraining the relaxed model?

Original source

Related problems