我已阅读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
,据说这是该文档中的一种可能行为。
此代码有什么错误吗?还是有误会?
答案 0 :(得分:8)
或者,有什么误会吗?
是的,只有一个。 std::memory_order_relaxed
在您的程序中所允许的是针对于体系结构的实现(编译器),以产生可能会观察到副作用r1 == r2 == 42
的程序。
实现不必产生这样的程序,并且这样的程序也不必产生副作用。无论如何这都是可能的结果。
如何测试std :: memory_order_relaxed的行为?
我看不到此问题的一般解决方案。您只能检查您所观察到的副作用是否符合std::memory_order_relaxed
的规范。
答案 1 :(得分:3)
您的代码有点天真,因为到第二个线程启动时,第一个线程可能已经完成。线程需要真正并发地运行这些代码。
要使r1 == r2 == 42
为真,需要将负载C
重新排序到存储D
之后,x86当前不执行存储之后重新排序的加载,因此您可能永远不会在这种平台上观察到这种重新排序(除非编译器将C
与D
重新排序)。