关于std::memory_order_consume

原文:https://preshing.com/20140709/the-purpose-of-memory_order_consume-in-cpp11/

翻译:C++11中memory_order_consume的目的

https://blog.csdn.net/netyeaxi/article/details/80718781

文章中有这样一个例子:

复制代码
g = Guard.load(memory_order_consume);
if (g != nullptr)
    p = *g;

既然g已经表明了代码级别的依赖,为什么还需要memory_order_consume,而不可以直接memory_order_relaxed呢?

搜了一下这里有个解释,但是它似乎没有说清楚:https://stackoverflow.com/questions/38280633/c11-the-difference-between-memory-order-relaxed-and-memory-order-consume

其实也比较简单,先看一下memory_order_release的规则(中英文对照方便理解):https://en.cppreference.com/w/cpp/atomic/memory_order

有此内存定序的存储操作进行释放操作:当前线程中的读或写不能被重排到此存储之后。

  1. 当前线程的所有写入,可见于获得该同一原子变量的其他线程(见下方释放-获得定序)
  2. 并且对该原子变量的带依赖写入变得对于其他消费同一原子对象的线程可见(见下方释放-消费定序)。

A store operation with this memory order performs the release operation: no reads or writes in the current thread can be reordered after this store.

  1. All writes in the current thread are visible in other threads that acquire the same atomic variable (see Release-Acquire ordering below)
  2. writes that carry a dependency into the atomic variable become visible in other threads that consume the same atomic (see Release-Consume ordering below).

注意第二条:在其他线程,使用consume能保证该原子变量的带依赖写入(文中的g)可见。换言之relaxed不能保证这一点。

也就是:

复制代码
Payload = 42;
Guard.store(&Payload, memory_order_release);

在另一个线程看起来可能是:

复制代码
Guard.store(&Payload, memory_order_release);
Payload = 42;

另外我们也能得到这样的结论:只使用memory_order_release,而不配合使用acquire或consume或其他更严格约束的话,对其他线程来说是没有意义的。

再推而广之,所有的memory_order都要在多个线程配合使用,才能影响变量在线程之间的可见性。根据这一点,也能理解为什么relaxed是不正确的。

相关推荐
你的牧游哥1 小时前
Java 核心概念详解
java·开发语言
Rabitebla1 小时前
C++ 和 C 语言实现 Stack 对比
c语言·数据结构·c++·算法·排序算法
旖-旎1 小时前
递归(汉诺塔问题)(1)
c++·学习·算法·leetcode·深度优先·递归
深邃-1 小时前
【数据结构与算法】-顺序表链表经典算法
java·c语言·数据结构·c++·算法·链表·html5
努力学习的小廉1 小时前
我爱学算法之—— 前缀和(上)
c++·算法
文祐1 小时前
C++类之虚函数表和虚基类表及其内存布局(一个子类虚继承一个父类)
开发语言·c++
是娇娇公主~1 小时前
C++11 移动语义全面详解
c++·移动语义
xyq20241 小时前
服务定位器模式
开发语言
努力努力再努力wz1 小时前
【MySQL入门系列】掌握表数据的 CRUD:DML 核心语法与执行逻辑解析
android·开发语言·数据结构·数据库·c++·b树·mysql