gpt4 book ai didi

c++ - 如何理解 std::memory_order (C++) 中的 RELAXED ORDERING

转载 作者:搜寻专家 更新时间:2023-10-31 00:51:15 32 4
gpt4 key购买 nike

我阅读了很多帖子并观看了几个 Youtube 视频 C++ 原子和内存模型(ConCpp 17、14)。

当我阅读Concurrency In Action一书的第 5.3.3 节,RELAXED ORDERING 时,我仍然无法理解作者在他的假设下提供的示例。

作者的假设

It’s not just that the compiler can reorder the instructions. Even if the threads are running the same bit of code, they can disagree on the order of events because of operations in other threads in the absence of explicit ordering constraints, because the different CPU caches and internal buffers can hold different values for the same memory. It’s so important I’ll say it again: threads don’t have to agree on the order of events. Not only do you have to throw out mental models based on interleaving operations, you also have to throw out mental models based on the idea of the compiler or processor reordering the instructions.

假设我们看到的代码没有重新排序

示例代码:

#include <atomic>
#include <thread>
#include <assert.h>

std::atomic<bool> x,y;
std::atomic<int> z;

void write_x_then_y()
{
x.store(true,std::memory_order_relaxed); // 1
y.store(true,std::memory_order_relaxed); // 2
}

void read_y_then_x()
{
while(!y.load(std::memory_order_relaxed)); // 3
if(x.load(std::memory_order_relaxed)) // 4
++z;
}

int main() {
x=false;
y=false;
z=0;

std::thread a(write_x_then_y);
std::thread b(read_y_then_x);
a.join();
b.join();

assert(z.load()!=0); // 5
}

来自此链接:https://www.developerfusion.com/article/138018/memory-ordering-for-atomic-operations-in-c0x/

enter image description here

为什么 x.load(relaxed)返回 false但是y.load(relaxed)返回 true

作者结论

This time the assert (5) can fire, because the load of x (4) can read false, even though the load of y (3) reads true and the store of x (1) happens-before the store of y (2). x and y are different variables, so there are no ordering guarantees relating to the visibility of values arising from operations on each.

问。为什么 x 的负载可以是假的?

作者得出的结论是 assert 可以触发。所以,z可以是0 .所以,if(x.load(std::memory_order_relaxed)) : x.load(std::memory_order_relaxed)false .

但无论如何,while(!y.load(std::memory_order_relaxed));使 y true .

如果我们不重新排序 (1) 和 (2) 的代码序列,怎么可能 y是真的但是x还是没有存储?

如何理解作者提供的图?

基于 the store of x (1) happens-before the store of y (2) , 如果 x.store(relaxed)之前发生 y.store(relaxed) , x应该是 true现在。但是为什么x还是false甚至 ytrue

最佳答案

您和 friend 都同意 x=falsey=false。有一天,您给他发了一封信,告诉他 x=true。第二天,您给他发了一封信,告诉他 y=true。您绝对以正确的顺序向他发送信件。

一段时间后,您的 friend 收到您的一封信,信中说 y=true。现在您的 friend 对 x 了解多少?他可能已经收到告诉他x=true 的信件。但也许邮政系统暂时丢失了它,他明天就会收到。所以对他来说,x=falsex=true 都是当他收到 y=true 信件时的有效可能性。

那么,回到硅世界。线程之间的内 stub 本不能保证来自其他线程的写入以任何特定顺序出现,因此“延迟 x”完全是可能的。所有添加 atomic 和使用 relaxed 所做的都是阻止两个线程在单个变量上竞争成为未定义的行为。它对订购没有任何保证这就是强排序的目的。

或者,以更粗略的方式,看看我的 MSPaint 技能:

enter image description here

在这种情况下,表示“x”从第一个线程流向第二个线程的紫色箭头来得太晚,而绿色箭头(y 交叉)发生得很快。

关于c++ - 如何理解 std::memory_order (C++) 中的 RELAXED ORDERING,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55680665/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com