memory_order_seq_cst如何与非原子操作同步?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了memory_order_seq_cst如何与非原子操作同步?相关的知识,希望对你有一定的参考价值。
如果使用单个原子变量和std::memory_order_seq_cst
,非原子操作是否保证不会被重新排序?
例如,如果我有
std::atomic<bool> quux = {false};
void foo() {
bar();
quux.store(true, std::memory_order_seq_cst);
moo();
}
bar()
保证不会在store
调用之后重新排序,并且moo()
不会在store
调用之前重新排序,只要我使用std::memory_order_seq_cst
,至少从另一个线程的角度来看?
或者,将它放在代码中,如果从另一个线程运行,以下假设是否有效?
if(quux.load(std::memory_order_seq_cst) == true) {
// bar guaranteed to be called; its side-effects are visible
// moo might have been called, but is not guaranteed to
} else {
// bar might have been called, but is not guaranteed to
// moo might have been called, but is not guaranteed to
}
请注意,我假设bar
和moo
都不使用原子操作,互斥锁,锁,围栏或其他同步功能。
如果使用单个原子变量和
std::memory_order_seq_cst
,非原子操作是否保证不会被重新排序?
这个http://en.cppreference.com/w/cpp/atomic/memory_order的标准很清楚:
memory_order_seq_cst
具有此内存顺序的任何操作都是获取操作和释放操作,并且存在单个总订单,其中所有线程以相同的顺序观察所有修改
memory_order_acquire
具有此内存顺序的加载操作会对受影响的内存位置执行获取操作:在此加载之前,不能对当前线程中的读取或写入进行重新排序。
memory_order_release
具有此内存顺序的存储操作执行释放操作:在此存储之后,当前线程中的任何读取或写入都不能重新排序。
换句话说,没有负载或存储(非原子和原子)可以在memory_order_seq_cst
操作周围重新排序。
bar()
保证在商店调用后不会重新排序,并且moo()
在商店调用之前不会重新排序,只要我使用std :: memory_order_seq_cst,至少从另一个线程的角度来看?
如果bar
和moo
的定义在当前转换单元中不可用,则编译器假定这些函数执行内存加载和/或具有副作用(执行I / O或存储到内存),因此无法围绕memory_order_seq_cst
操作重新排序。
如果定义可用且函数不执行I / O或内存加载/存储,则可以重新排序。这些将是pure functions或什么都不做的功能,并返回void
或常量。
根据由@Maxim链接的链接http://en.cppreference.com/w/cpp/atomic/memory_order,关于memory_order_seq_cst存在错误。上面的文本与memory_order_acq_rel交换。 memory_order_seq_cst的文本:
memory_order_seq_cst:具有此内存顺序的加载操作执行获取操作,存储执行释放操作,读取 - 修改 - 写执行获取操作和释放操作,以及存在单个总订单,其中所有线程都观察所有修改以相同的顺序(参见下面的顺序一致排序)
因此,在您的情况下,存储操作等同于释放,这意味着可以在栅栏之前重新排序moo()。
因为使用了最严格的内存顺序,所以函数bar和moo不能分别在商店之前或之前重新排序。
你对if-else案的结论并不完全正确。
如果表达式if(quux.load(std::memory_order_seq_cst) == true)
的计算结果为true,那么函数栏肯定已经完成了它的调用。无法确定对moo的调用顺序。它可能已经完成,没有开始,或者它可能在通话中间。
如果提到的表达式求值为false,那么我们无法确定两个函数的顺序。虽然表达式的计算结果为false,但函数moo尚未被调用,可能在执行之后,在执行进入else子句之前调用它。一旦进入else子句,函数moo的状态与前一段中的状态相同(无法确定)。
以上是关于memory_order_seq_cst如何与非原子操作同步?的主要内容,如果未能解决你的问题,请参考以下文章
memory_order_seq_cst 和 memory_order_acq_rel 有何不同?
为啥在已经使用 seq_cst CAS 的无锁队列中需要 atomic_thread_fence(memory_order_seq_cst)?
Array.Sort 谷歌内核 数组大小超过10 排序字段都一致 返回的数组非原数组