我目前在内存模型部分(第 5 章)中阅读了“C++ Concurrency in action”。在第 5.3.1 章中,作者写道:
#include <vector>
#include <atomic>
#include <iostream>
std::vector<int> data;
std::atomic<bool> data_ready(false);
void reader_thread()
{
while(!data_ready.load()) // (1)
{
std::this_thread::sleep(std::milliseconds(1));
}
std::cout<<”The answer=”<<data[0]<<”\n”; // (2)
}
void writer_thread()
{
data.push_back(42); // (3)
data_ready=true; // (4)
}
抛开等待数据准备好的循环的低效率(1),你真的需要它来工作,因为否则在线程之间共享数据变得不切实际:每一项数据都被迫成为原子的。您已经了解到,非原子读取(2)和写入(3)在没有强制排序的情况下访问相同的数据是未定义的行为,因此要使其工作,必须在某处强制排序。
所需的强制排序来自对 std:: 原子变量 data_ready 的操作;它们通过发生在之前和同步的内存模型关系提供必要的排序。数据的写入(3)发生在数据就绪标志(4)的写入之前,标志(1)的读取发生在数据的读取(2)之前。当从 data_ready (1)读取的值为真时,写入与读取同步,创建发生前的关系。因为happens-before是传递性的,所以对数据的写入(3)发生在写入标志(4)之前,发生在从标志(1)读取真值之前,发生在读取之前数据(2),你有一个强制的顺序:数据的写入发生在数据的读取之前,一切正常。图 5。图 2 显示了两个线程中的重要发生之前的关系。我从阅读器线程中添加了几次 while 循环的迭代。
所有这些看起来都相当直观:当然,写入值的操作发生在读取该值的操作之前!对于默认的原子操作,这确实是真的(这就是为什么这是默认的),但它确实需要说明:原子操作还有其他选项来满足排序要求,我很快就会谈到
我很不明白,为什么“所有这些看起来都相当直观:当然,写入值的操作发生在读取该值的操作之前!”,请帮助我理解这句话。