轻松排序标记为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)已被切换
答案 0 :(得分:3)
之前(与发生在之前)的关系不是特定于多线程的。它们也发生在单线程程序中。任何以分号结尾的表达式都是在之前序列,所以在这种情况下,A
在B
和C
D
之前排序因为他们每个人都是一个完整的表达。
从标准 1.9程序执行14 :
与全表达相关的每个值计算和副作用在每个值之前排序 计算和副作用与下一个要评估的完整表达相关联。
您可以在此处找到解释:
答案 1 :(得分:1)
"测序-之前"适用于程序的可见可观察行为。编译器可以以任何方式自由地达到该行为;只要可见行为相同,它就可以重新排序写入内存或完全消除它们。
答案 2 :(得分:-3)
该问题无法回答。没有标准的线程语义,故事的结尾。
说存在标准化的线程语义或任何程序的任何语义都是骗局。