作为我之前question的后续内容,atomic<T>
类使用memory_order
参数指定大多数操作。与围栏相比,此内存顺序仅影响其运行的原子。大概通过使用几个这样的原子,你可以构建一个并发算法,其他内存的排序是不重要的。
所以我有两个问题:
答案 0 :(得分:4)
std::atomic<T>
变量操作的内存排序参数不会影响该操作本身的排序,它会影响操作与其他操作创建的排序关系。
e.g。 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
并添加显式围栏,那么编译器可能必须明确地将这些围栏作为指令发布。
e.g。在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);
但是,我还没有发现任何编译器摆脱以下代码中的显式fence指令:
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
只能 才能应用于对变量的直接操作。