在修改顺序一致性之前排序

时间:2014-12-13 19:45:13

标签: c++ atomic

来自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

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

问题:对于上述代码,在之前对属性 A进行排序,并且在之前对 C进行排序>

修改

int A, B;

void foo()
{
    A = B + 1; (A)
    B = 0; (B)
}

导致

$ 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
        ...

在GCC 4.6.1下使用-02选项

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

3 个答案:

答案 0 :(得分:3)

之前(与发生在之前)的关系不是特定于多线程的。它们也发生在单线程程序中。任何以分号结尾的表达式都是之前序列,所以在这种情况下,ABC D之前排序因为他们每个人都是一个完整的表达。

从标准 1.9程序执行14

  

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

您可以在此处找到解释:

Order of evaluation

答案 1 :(得分:1)

"测序-之前"适用于程序的可见可观察行为。编译器可以以任何方式自由地达到该行为;只要可见行为相同,它就可以重新排序写入内存或完全消除它们。

答案 2 :(得分:-3)

该问题无法回答。没有标准的线程语义,故事的结尾。

说存在标准化的线程语义或任何程序的任何语义都是骗局。