如何测试std :: memory_order_relaxed的行为?

时间:2018-09-06 08:36:18

标签: c++ multithreading stl atomic memory-barriers

我已阅读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,据说这是该文档中的一种可能行为。

此代码有什么错误吗?还是有误会?

2 个答案:

答案 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当前不执行存储之后重新排序的加载,因此您可能永远不会在这种平台上观察到这种重新排序(除非编译器将CD重新排序)。

另一方面,ARM和PowerPC的内存模型较弱。请参阅Runtime memory ordering 表。