标记为 std::memory_order_seq_cst 的单个原子操作会在所有地方触发顺序一致性吗?
Does a single atomic operation marked as std::memory_order_seq_cst trigger sequential consistency everywhere?
顺序一致性对所有线程施加了所有原子操作的全局顺序。据我所知,这意味着线程将按照源代码中指定的方式运行,不会重新排序。所有线程将按顺序执行它们的操作。
直觉上,它看起来像是要在多线程应用程序的 main()
函数中设置的选项或标志,类似于 "I want all my threads to follow sequential consistency"。当然在C++中没有这样的东西。
所以这是我的问题:代码中任何地方仅存在一条 x.load(std::memory_order_seq_cst)
或 x.store(y, std::memory_order_seq_cst)
指令就足以强制所有线程,甚至是那些与 x
无关的线程以顺序一致的方式?
不,memory_order_seq_cst
只保证所有memory_order_seq_cst
原子accesses/fences的总序,见C++17标准终稿[atomics.order]/3。它不会将该要求强加于其他内存访问,即使是内存顺序较弱的原子访问。
例如,如果对于两个用 0
初始化的原子变量 std::atomic<int> x{0}, y{0};
,线程 1 执行
x.store(1, std::memory_order_seq_cst);
并且线程 2 执行
y.store(1, std::memory_order_relaxed);
线程 3 和 4 执行时
auto a = x.load(std::memory_order_relaxed);
auto b = y.load(std::memory_order_relaxed);
然后线程 3 可以,例如观察 a == 1
和 b == 0
,而线程 4 观察 a == 0
和 b == 1
。 y
不通过任何 memory_order_seq_cst
操作访问,也不与 x
存储排序。因此,没有单一的线程间排序来确定 x
和 y
上的存储发生的顺序。
在 C++17 标准最终草案的 [atomics.order]/8.
节中也有关于这一点的说明
顺序一致性对所有线程施加了所有原子操作的全局顺序。据我所知,这意味着线程将按照源代码中指定的方式运行,不会重新排序。所有线程将按顺序执行它们的操作。
直觉上,它看起来像是要在多线程应用程序的 main()
函数中设置的选项或标志,类似于 "I want all my threads to follow sequential consistency"。当然在C++中没有这样的东西。
所以这是我的问题:代码中任何地方仅存在一条 x.load(std::memory_order_seq_cst)
或 x.store(y, std::memory_order_seq_cst)
指令就足以强制所有线程,甚至是那些与 x
无关的线程以顺序一致的方式?
不,memory_order_seq_cst
只保证所有memory_order_seq_cst
原子accesses/fences的总序,见C++17标准终稿[atomics.order]/3。它不会将该要求强加于其他内存访问,即使是内存顺序较弱的原子访问。
例如,如果对于两个用 0
初始化的原子变量 std::atomic<int> x{0}, y{0};
,线程 1 执行
x.store(1, std::memory_order_seq_cst);
并且线程 2 执行
y.store(1, std::memory_order_relaxed);
线程 3 和 4 执行时
auto a = x.load(std::memory_order_relaxed);
auto b = y.load(std::memory_order_relaxed);
然后线程 3 可以,例如观察 a == 1
和 b == 0
,而线程 4 观察 a == 0
和 b == 1
。 y
不通过任何 memory_order_seq_cst
操作访问,也不与 x
存储排序。因此,没有单一的线程间排序来确定 x
和 y
上的存储发生的顺序。
在 C++17 标准最终草案的 [atomics.order]/8.
节中也有关于这一点的说明