from http://en.cppreference.com :
Relaxed ordering Atomic operations tagged std::memory_order_relaxed are not synchronization operations, they do not order memory. They only guarantee atomicity and modification order consistency. For example, with x and y initially zero,
// Thread 1:
r1 = y.load(memory_order_relaxed); // A
x.store(r1, memory_order_relaxed); // B
// Thread 2:
r2 = x.load(memory_order_relaxed); // C
y.store(42, memory_order_relaxed); // D
is allowed to produce r1 == r2 == 42 because, although A is sequenced-before B and C is sequenced before D, nothing prevents D from appearing before A in the modification order of y, and B from appearing before C in the modification order of x.
Question: What it is the thing that confer to the above code the property A is sequenced-before B and C is sequenced before D?
EDIT:
int A, B;
void foo()
{
A = B + 1; (A)
B = 0; (B)
}
lead to
$ gcc -O2 -S -masm=intel foo.c
$ cat foo.s
...
mov eax, DWORD PTR B
mov DWORD PTR B, 0
add eax, 1
mov DWORD PTR A, eax
...
under GCC 4.6.1 with -02 option
so we clearly see that (A) and (B) have been switched
The sequenced-before (not the same as happens-before) relationships are not specific to multithreading. They happen in single threaded programs as well. Any expression that ends with a semicolon is sequenced-before the next, so in this case A
is sequenced before B
and C
before D
because each of them is a full-expression.
From the Standard 1.9 Program execution 14:
Every value computation and side effect associated with a full-expression is sequenced before every value computation and side effect associated with the next full-expression to be evaluated.
You can find an explanation here: