我读过std::memory_order_relaxed的文档。
放松订购的一部分解释是....
// 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
。特别是,如果由于编译器重新排序或在运行时由D在线程2中的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;
}
这段代码的结果绝不是r1 == r2 == 42
,据说这是该文档中的一种可能行为。
这段代码有什么问题吗?或者,有任何误解吗?
或者,有任何误解吗?
是的,有一个。 std::memory_order_relaxed
在您的程序中允许的是针对架构的实现(编译器),以生成可以观察副作用r1 == r2 == 42
的程序。
实现不必生成这样的程序,并且这样的程序不必产生那种副作用;无论如何,这可能是一个结果。
如何测试std :: memory_order_relaxed的行为?
我看不出这个问题的一般解决方案。您只能检查您观察到的副作用是否与std::memory_order_relaxed
的规格匹配。
你的代码有点天真,因为当第二个线程开始时,第一个线程可能已经完成。线程需要真正同时运行这些代码。
要使r1 == r2 == 42
为真,它需要加载C
重新排序经过商店D
,x86不会在当前存储之后重新排序负载,因此您可能永远不会在此平台上观察到这种重新排序(除非编译器使用C
重新排序D
)。
另一方面,ARM和PowerPC具有较弱的内存模型。见Runtime memory ordering 表。