【发布时间】:2019-02-11 11:15:40
【问题描述】:
我已经阅读了std::memory_order_relaxed的文档。
Relaxed ordering的部分解释是......
// 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
这就是说的解释……
[It] 可以产生
r1 == r2 == 42。特别是,如果由于编译器重新排序或在运行时,线程 2 中的 D 在 C 之前完成,则可能会发生这种情况。
我已经理解了解释,并尝试在我的电脑上测试如下代码:
std::atomic<int> x = {0};
std::atomic<int> y = {0};
int r1, r2;
void task1() {
// Thread 1:
r1 = y.load(memory_order_relaxed); // A
x.store(r1, memory_order_relaxed); // B
}
void task2() {
// Thread 2:
r2 = x.load(memory_order_relaxed); // C
y.store(42, memory_order_relaxed); // D
}
int main()
{
std::thread t2 (task2);
std::thread t1 (task1);
t1.join();
t2.join();
cout << "r1: " << r1
<< "\nr2: " << r2 << endl;
return 0;
}
这段代码的结果是never r1 == r2 == 42,据说这是该文档中的一种可能行为。
这段代码有什么问题吗?或者,是不是有什么误会?
【问题讨论】:
-
我明天中奖1000000是可能。但这可能。我可以尝试一生,永远不会中奖。 有人会赢。
-
x86 上的内存排序至少是获取释放。所以你不会在经典计算机上看到
r1==r2==42。也许如果你以 ARM CPU 为目标,你可以看到它。 -
@Olive 这并不完全正确。 硬件 永远不会重新排序这些操作,但允许编译器根据语言规范重新排序它们(在不同的原子上)。观察到的行为取决于编译器是否实际上这样做。
-
@Oliv:也在多插槽设置上?您通常具有有限的非统一内存访问;每个内存模块只直接连接到一个 CPU。
-
@ArneVogel 理论上是的。但直到今天,所有编译器都将原子视为也被声明为 volatile。例如,编译器甚至不会优化存储在同一个函数内执行的单个原子上的两个连续的,即使标准允许这样做。
标签: c++ multithreading stl atomic memory-barriers