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

问题描述 投票:5回答:2

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

这段代码有什么问题吗?或者,有任何误解吗?

c++ multithreading stl atomic memory-barriers
2个回答
8
投票

或者,有任何误解吗?

是的,有一个。 std::memory_order_relaxed在您的程序中允许的是针对架构的实现(编译器),以生成可以观察副作用r1 == r2 == 42的程序。

实现不必生成这样的程序,并且这样的程序不必产生那种副作用;无论如何,这可能是一个结果。

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

我看不出这个问题的一般解决方案。您只能检查您观察到的副作用是否与std::memory_order_relaxed的规格匹配。


3
投票

你的代码有点天真,因为当第二个线程开始时,第一个线程可能已经完成。线程需要真正同时运行这些代码。

要使r1 == r2 == 42为真,它需要加载C重新排序经过商店D,x86不会在当前存储之后重新排序负载,因此您可能永远不会在此平台上观察到这种重新排序(除非编译器使用C重新排序D)。

另一方面,ARM和PowerPC具有较弱的内存模型。见Runtime memory ordering 表。

© www.soinside.com 2019 - 2024. All rights reserved.