排序前修改顺序一致性

Gui*_*e07 6 c++ multithreading memory-model stdatomic instruction-reordering

来自http://en.cppreference.com

宽松排序标记 std::memory_order_relaxed 的原子操作不是同步操作,它们不排序内存。它们只保证原子性和修改顺序的一致性。例如,x 和 y 最初为零,

// 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
Run Code Online (Sandbox Code Playgroud)

允许产生 r1 == r2 == 42 因为,虽然 A 在 B 之前被排序并且 C 在 D 之前被排序,但是没有什么可以阻止 D 在 y 的修改顺序中出现在 A 之前,并且 B 在修改中出现在 C 之前x 的顺序。

问题:是什么赋予上述代码属性A 在 B 之前排序并且C 在 D 之前排序

编辑:

int A, B;

void foo()
{
    A = B + 1; (A)
    B = 0; (B)
}
Run Code Online (Sandbox Code Playgroud)

导致

$ 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
        ...
Run Code Online (Sandbox Code Playgroud)

在带有 -02 选项的 GCC 4.6.1 下

所以我们清楚地看到(A)和(B)已经切换

imr*_*eal 5

测序-之前(不一样的之前发生)的关系并非专门针对多线程。它们也发生在单线程程序中。任何以分号结尾的表达式都在下一个之前,所以在这种情况下A,排在前面BC之前,D因为它们中的每一个都是一个完整的表达式。

从标准1.9 程序执行 14

与完整表达式相关的每个值计算和副作用在与要评估的下一个完整表达式相关的每个值计算和副作用之前排序。

你可以在这里找到解释:

评估顺序

  • @Guillaume07 *sequenced-before* 关系仅在线程内计数。这意味着第一个线程将在“B”的副作用之前看到“A”的副作用,但不能保证第二个线程将看到它们的顺序。 (2认同)