作为我之前的 question 的后续, atomic<T>
类使用 memory_order
参数指定大多数操作。与栅栏相反,此内存顺序仅影响其操作的原子。大概通过使用几个这样的原子,您可以构建一个并发算法,其中其他内存的排序不重要。
所以我有两个问题:
最佳答案
std::atomic<T>
变量上操作的内存排序参数不会 而不是 影响该操作本身的排序,它会影响操作与其他操作创建的排序关系。
例如a.store(std::memory_order_release)
本身并没有告诉你关于 a
上的操作是如何相对于其他任何东西排序的,但与从另一个线程对 a.load(std::memory_order_acquire)
的调用配对,这然后命令 其他 操作 --- 所有写入 其他变量 (包括非原子的)由执行存储到 a
的线程完成,如果该加载读取存储的值,则对执行加载的线程可见。
在现代处理器上,某些操作的内存排序是无操作的。例如在 x86 上, memory_order_acquire
、 memory_order_consume
和 memory_order_release
隐含在加载和存储指令中,不需要单独的栅栏。在这些情况下,排序只会影响编译器可以执行的指令重新排序。
说明:指令中的隐式栅栏意味着如果所有内存排序约束都附加到原子变量上的单个操作,则编译器不需要发出 任何 显式栅栏指令。如果您对所有内容都使用 memory_order_relaxed
,并添加显式围栏,那么编译器可能必须显式发出这些围栏作为指令。
例如在 x86 上,XCHG
指令带有一个隐式的 memory_order_seq_cst
栅栏。因此,在 x86 上为以下两个交换操作生成的代码之间没有区别——它们都映射到单个 XCHG
指令:
std::atomic<int> ai;
ai.exchange(3,std::memory_order_relaxed);
ai.exchange(3,std::memory_order_seq_cst);
但是,我还不知道有任何编译器可以消除以下代码中的显式围栏指令:
std::atomic_thread_fence(std::memory_order_seq_cst);
ai.exchange(3,std::memory_order_relaxed);
std::atomic_thread_fence(std::memory_order_seq_cst);
我希望编译器最终会处理这种优化,但还有其他类似的情况,隐式栅栏将允许更好的优化。
此外,
std::memory_order_consume
只能将 应用于对变量的直接操作。关于C++0X memory_order无围栏,应用程序,芯片支持,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/5561889/