了解 C++ 中的顺序一致性栅栏

Sou*_*a B 6 c++ memory-barriers stdatomic

我正在阅读有关 C++ 中的内存顺序的内容。我可以很好地理解放松和获取-释放模型。但我正在努力解决顺序一致性问题。

如果我没记错的话,从cppreference来看,std::memory_order_seq_cst“操作”相当于:

  • 当操作为“加载”时,获取操作加上单个总订单。
  • 当操作为“存储”时,释放操作加上单个总订单。
  • 当操作为“读-修改-写”时,acq-rel 操作加上单个全序。

std::memory_order_seq_cst但‘栅栏’又是怎样的情况呢?它相当于其中的哪一个?

  • 获取栅栏加上单个总订单。
  • 释放栅栏加上单个总订单。
  • 一个 acq-rel 围栏加上一个总订单。

如果和上面其中之一是等价的,那另外两个呢?

据我所知,如果是情况 1(获取栅栏),编译器可以自由地将任何写操作从栅栏上方移动到栅栏下方。类似地,如果是情况 2(释放栅栏),编译器可以自由地将任何读取操作从栅栏下方移动到栅栏上方。最后,如果是情况 3(acq-rel 栅栏),则不允许编译器跨栅栏移动任何指令。它是否正确?

我仍然很困惑。以上说法可能不正确。有不对的地方请指正。

Nat*_*dge 2

简而言之,就是情况3。

栅栏seq_cst包含栅栏的所有功能acq_rel。参见 [atomics.fences p5.5]:

是一个顺序一致的获取和释放栅栏,如果order == memory_order::seq_cst.

因此,它特别是一个获取和释放栅栏。而且它也是一个顺序一致的栅栏,这意味着它以与那里规定的规则一致的方式包含在[atomics.order p4]中定义的总顺序S中。

正式的C++内存模型没有“重新排序”的概念。然而,您是对的,seq_cst栅栏的典型实现是防止负载和存储在任一方向上重新排序。请注意,这比acq_rel栅栏严格更强,这将允许栅栏之前的存储与栅栏之后的负载一起重新排序(StoreLoad 重新排序)。