我正在阅读关于C++内存模型的“C++”第5.3节,下面的清单5.5让我感到困惑:
std::atomic<bool> x,y;
std::atomic<int> z;
void write_x_then_y()
{
// Is there a Happens-Before relationship for statement (1) and (2) below?
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));
if(x.load(std::memory_order_relaxed))
++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);
}让我困惑的是函数void write_x_then_y()。作者说,“这次在main() can 末尾的断言”和关于原子变量x的语句(1)在与原子变量y的语句(2)的“发生之前”的关系。但是我认为在std::memory_order_relaxed,中不同的原子变量之间没有同步,编译器/CPU可以在不违反程序语义的情况下重新排序这两条语句。
清单5.5中的关系之前发生的情况如图5.4所示,以及可能的结果。

发布于 2022-07-03 01:49:32
在进行另一次评估之前对其进行排序的评估。
前排序是同一线程中的计算之间的关系,它独立于同步机制,例如具有非松弛内存顺序的原子负载/存储。
通过在线程之间加入同步机制,将计算顺序的排序关系从单线程情况扩展到多线程情况。
有关确切定义,请参见订单。
在一条语句之前的一条语句中的求值总是排序--在后一条语句之前。(基本上在两个语句之间有一个序列点,尽管自C++11以来不再使用这个术语。)
编译器可以重新排序这两个轻松的存储。这并不影响发生之前的关系,尽管。仅仅因为两个存储(在不同的atomics上)发生--在彼此之前--并不意味着不能通过另一个线程以不同的顺序观察存储,如图中的示例所示。
您需要在负载和存储之间建立一个发生之前的关系,以防止显示的结果。为此,需要以某种方式进行线程间排序,例如通过释放/获取原子操作。基本上,您需要在图中的灰色框之间建立一些箭头。
https://stackoverflow.com/questions/72843313
复制相似问题