c++ - 我们是否可以保证任何原子写入都会立即将原子变量的新值存储在主内存中?

标签 c++ cpu-cache memory-model stdatomic instruction-reordering

所以,我阅读了很多关于指令和内存重新排序以及我们如何防止它的内容,但我仍然没有回答一个问题(可能是因为我不够专心)。我的问题是:我们是否可以保证任何原子写入都会立即将原子变量的新值存储在主内存中? 让我们看一个小例子:

std::atomic<bool> x;
std::atomic<bool> y;
std::atomic<int> count;
void WritingValues()
{
   x.store(true, std::memory_order_relaxed);
   y.store(true, std::memory_order_relaxed);
}
void ReadValues()
{
   while( !y.load(std::memory_order_relaxed) );
   if( x.load(std::memory_order_relaxed) )
       ++count;
}
int main()
{
   x = false;
   y = false;
   count = 0;
   std::thread tA(WritingValues);
   std::thread tB(ReadValues);
   tA.join();
   tB.join();
   assert( count.load() != 0 );
}

因此,这里我们的断言肯定会触发,因为我们使用 std::memory_order_relaxed 并且不会阻止任何指令重新排序(或编译时的内存重新排序,我想这是一回事)。但是,如果我们在 WritingValues 中放置一些编译器屏障以防止指令重新排序,一切都会好起来吗?我的意思是,x.store(true, std::memory_order_relaxed) 是否保证那个特定原子变量 的写入将直接写入内存,没有任何延迟?还是 x.load(std::memory_order_relaxed) 保证值将从内存中读取,而不是从具有无效值的缓存中读取?换句话说,这个存储保证操作的原子性,并具有与通常的非原子变量相同的内存行为,或者它也对内存行为有影响?

最佳答案

 I mean, does x.store(true, std::memory_order_relaxed) guarantees, that the  
 of that particular atomic variable will be directly into the memory,  
 without any latency?  

不,它没有,事实上,给定 bool 和内存顺序放松,如果你只读一次,就没有“无效”值,true 和 false 都可以。
由于宽松的内存顺序明确保留,因此不执行任何排序。基本上,在您的情况下,它仅意味着在从 false 变为 true 之后,在某个时候它将对所有其他进程变为 true,但没有说明“何时”会发生。所以这里唯一可以确定的是,它变成真后不会再变成假了。但是对于它在另一个线程中为假多长时间没有限制。
它还保证您不会在另一个线程中看到任何部分写入的变量,但 bool 值几乎不是这种情况。
你需要在这里使用 aquire 和 release 。即使这样也不能对实际内存本身提供任何保证,只能保证程序行为,缓存同步甚至可以在不将数据弹回内存的情况下发挥作用。

关于c++ - 我们是否可以保证任何原子写入都会立即将原子变量的新值存储在主内存中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57431572/

相关文章:

assembly - 缓存未命中会陷入哪些危险?

linux - 为什么下面的代码无法输出 Hello World?

c++ - 可以在 C++ 内存模型中合并原子负载吗?

C++WinApi : GetClientRect fails

c++ - 将 std::error_code 与整数进行比较

c++ - 如何在C++中使用条件检查typename T是否为整数类型的浮点类型

c++ - 现代处理器(如i7)会在遍历指针列表时跟随指针并预取其数据吗?

java - 在数据竞争期间,线程能否读取 volatile 变量的初始空值?特别是在构造函数中为其分配了非空值时?

c++ - 独立的读-修改-写顺序

c++ - 什么是三法则?