C++11 Memory Order

问题

C++11 Memory Order 的出现是为了解决什么样的问题?根据 [2] 的回答,我认为主要是为了解决 “指令重排” 带来的影响,指令重排是编译器或 CPU 为了优化性能而引入的。指令重排所带来的问题就是,多线程执行的时候,即使我们用一个 “原子变量” 来保证了内存的可见性,但是我们仍然无法确定这个 “原子变量” 前后的代码是否按照顺序执行了。[4] 非常简单,形象讲解了 Memory Order 要解决的问题,列举了三个问题,不过我认为主要是为了解决 “指令重排” 的问题。[4] 是非常好的参考资料。

[2] 最后的总结很独到:

它本身与多线程无关,是限制的单一线程当中指令执行顺序。但是(合理的)指令执行顺序的重排在单线程环境下不会造成逻辑错误而在多线程环境下会,所以这个问题的目的是为了解决多线程环境下出现的问题。

Memory Order 限制的是单线程的指令执行顺序,但是解决的是多线程执行情况下出现的问题。

Memory Order

在 C++11 中,定义了 6 种 Memory Order。

typedef enum memory_order
{
  memory_order_relaxed,
  memory_order_consume,
  memory_order_acquire,
  memory_order_release,
  memory_order_acq_rel,
  memory_order_seq_cst
} memory_order;

[1][3] 对以上的 Memory Order 做了简要的说明,下面记录一下自己的理解,Memory Order 本质上是限制了指令的执行顺序。

  • relaxed: 原子操作前后的指令,在另一个线程看来是任意的
  • release/comsume: 一个线程 release 之前的所有写,对另一个线程 acquire 之后的所有读可见
  • release/acquire: 只针对依赖的变量,一个线程 release 之前的所有写,对另一个线程 acquire 之后的所有读可见
  • acq_rel: 在当前操作的前后,前面的所有写,对后面的所有读可见。
  • seq_cst: 顺序一致性,所有指令严格按照顺序执行

总结一下:记住它要解决的问题,指令重排!Memory Order 提供了不同的选项,根据场景来选择以提高性能。

参考资料

[1] https://changkun.de/modern-cpp/zh-cn/07-thread/index.html
[2] 文礼的回答 - 知乎 https://www.zhihu.com/question/24301047/answer/1193956492
[3] zlilegion的回答 - 知乎 https://www.zhihu.com/question/24301047/answer/85844428
[4] http://senlinzhan.github.io/2017/12/04/cpp-memory-order/

原文地址:https://www.cnblogs.com/zzk0/p/15521489.html