C++ std原子同步和非原子变量:不是过时数据?

C++ std原子同步和非原子变量:不是过时数据?,c++,multithreading,c++11,atomic,C++,Multithreading,C++11,Atomic,我知道此代码是正确的(除了删除未完成): #包括 #包括 #包括 #包括 std::原子ptr; int数据; 无效生产者() { std::string*p=newstd::string(“Hello”); 数据=42; ptr.存储(p,std::内存\订单\发布); } 无效消费者() { std::string*p2; 而(!(p2=ptr.load(std::memory\u order\u acquire))) ; assert(*p2==“Hello”);//从不激发 断言(数据=

我知道此代码是正确的(除了
删除
未完成):

#包括
#包括
#包括
#包括
std::原子ptr;
int数据;
无效生产者()
{
std::string*p=newstd::string(“Hello”);
数据=42;
ptr.存储(p,std::内存\订单\发布);
}
无效消费者()
{
std::string*p2;
而(!(p2=ptr.load(std::memory\u order\u acquire)))
;
assert(*p2==“Hello”);//从不激发
断言(数据==42);//从不激发
}
int main()
{
std::线程t1(生产者);
标准:螺纹t2(耗电元件);
t1.join();t2.join();
}

但是,我想知道为什么消费者线程中的数据不能是陈旧的数据。是因为
acquire
操作吗?

分配给
data
ptr.store
调用。访问
数据
发生在该调用之后(是的,通过与原子对象同步的方式)。因此,保证访问可以看到先前分配的值

编译器必须确保变量的读取遵守在读取之前发生的写入所分配的最后一个值。如何实现这一点是一个实施细节;通常,它会发出一条特定于CPU的指令。那么,这会走多远呢?对该函数中所有内容的每个赋值是否都受到
ptr
提供的屏障的保护?简单地说:release=>刷新缓存。获取=>使缓存无效。消费操作要复杂得多。^^^@LightnessRacesinOrbit不要这样想<代码>标准::字符串
构造函数对对象的成员进行一系列赋值。如果
consumer
在获取
ptr
指针后看到
*ptr
的完全初始化状态,我想您不会感到惊讶。这与
数据
起作用的原因相同。@AntoineMorrier FWIW,将获取释放语义作为刷新缓存的理由是有害的。这可能导致错误的印象,即这些原子操作必然有运行时成本。对于像x86这样具有强内存模型的CPU,大多数存储指令已经具有acquire release语义,而
std::atomic
+
memory\u order\u release
只是为了防止编译时重新排序,机器代码没有区别。如果您不想使用
std::atomic
,使用带有伪
asm(“:”内存”)的普通变量就足够了。