memory_order_seq_cst 如何与非原子操作同步?
How does memory_order_seq_cst synchronize with non-atomic operations?
如果使用单个原子变量和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
都不使用原子操作、互斥、锁、栅栏或其他同步功能。
If one uses a single atomic variable and std::memory_order_seq_cst
, are non-atomic operations guaranteed not to be reordered?
这个标准很清楚http://en.cppreference.com/w/cpp/atomic/memory_order:
memory_order_seq_cst
A load operation with this memory order performs an acquire operation, a store performs a release operation, and read-modify-write performs both an acquire operation and a release operation, plus a single total order exists in which all threads observe all modifications in the same order.
memory_order_acquire
A load operation with this memory order performs the acquire operation on the affected memory location: no reads or writes in the current thread can be reordered before this load.
memory_order_release
A store operation with this memory order performs the release operation: no reads or writes in the current thread can be reordered after this store.
换句话说,无法围绕 memory_order_seq_cst
操作对加载或存储(非原子和原子)进行重新排序。
is bar()
guaranteed not to get reordered after the call of store, and moo()
not to get reordered before the call of store, as long as I use std::memory_order_seq_cst, at least from the perspective of another thread?
如果 bar
和 moo
的定义在当前翻译单元中不可用,编译器假定这些函数做内存加载 and/or 有副作用(做 I/O 或存储到内存),因此不能围绕 memory_order_seq_cst
操作重新排序。
如果定义可用且函数不执行 I/O 或记忆 loads/stores,则可以重新排序它们。这些将是 pure functions 或什么都不做的函数和 return void
或常数。
因为使用了最严格的内存顺序,函数 bar 和 moo 不能分别在存储到 quux 之后或之前重新排序。
您对 if-else 情况的结论不太正确。
如果表达式 if(quux.load(std::memory_order_seq_cst) == true)
的计算结果为真,那么函数 bar 肯定已经完成了它的调用。无法确定调用 moo 的顺序。它可能已经结束,没有开始,或者它可能正在通话中。
如果上述表达式的计算结果为假,那么我们无法确定这两个函数的顺序。虽然此时表达式的计算结果为假,但函数 moo 还没有被调用,它可能会在执行到 else 子句之前被调用。一旦进入else子句,函数moo的状态就和上一段一样了(无法确定)。
根据@Maxim 编辑的 link http://en.cppreference.com/w/cpp/atomic/memory_order link,上面的 memory_order_seq_cst.The 文本与 memory_order_acq_rel 交换时存在错误. memory_order_seq_cst 的文本:
memory_order_seq_cst:这个内存顺序的load操作执行acquire操作,store执行release操作,read-modify-write同时执行acquire操作和release操作,加单总存在所有线程以相同顺序观察所有修改的顺序(参见下面的 Sequentially-consistent 排序)
所以在你的例子中,存储操作等同于释放,这意味着 moo() 可以在栅栏之前重新排序。
如果使用单个原子变量和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
都不使用原子操作、互斥、锁、栅栏或其他同步功能。
If one uses a single atomic variable and
std::memory_order_seq_cst
, are non-atomic operations guaranteed not to be reordered?
这个标准很清楚http://en.cppreference.com/w/cpp/atomic/memory_order:
memory_order_seq_cst
A load operation with this memory order performs an acquire operation, a store performs a release operation, and read-modify-write performs both an acquire operation and a release operation, plus a single total order exists in which all threads observe all modifications in the same order.
memory_order_acquire
A load operation with this memory order performs the acquire operation on the affected memory location: no reads or writes in the current thread can be reordered before this load.
memory_order_release
A store operation with this memory order performs the release operation: no reads or writes in the current thread can be reordered after this store.
换句话说,无法围绕 memory_order_seq_cst
操作对加载或存储(非原子和原子)进行重新排序。
is
bar()
guaranteed not to get reordered after the call of store, andmoo()
not to get reordered before the call of store, as long as I use std::memory_order_seq_cst, at least from the perspective of another thread?
如果 bar
和 moo
的定义在当前翻译单元中不可用,编译器假定这些函数做内存加载 and/or 有副作用(做 I/O 或存储到内存),因此不能围绕 memory_order_seq_cst
操作重新排序。
如果定义可用且函数不执行 I/O 或记忆 loads/stores,则可以重新排序它们。这些将是 pure functions 或什么都不做的函数和 return void
或常数。
因为使用了最严格的内存顺序,函数 bar 和 moo 不能分别在存储到 quux 之后或之前重新排序。
您对 if-else 情况的结论不太正确。
如果表达式 if(quux.load(std::memory_order_seq_cst) == true)
的计算结果为真,那么函数 bar 肯定已经完成了它的调用。无法确定调用 moo 的顺序。它可能已经结束,没有开始,或者它可能正在通话中。
如果上述表达式的计算结果为假,那么我们无法确定这两个函数的顺序。虽然此时表达式的计算结果为假,但函数 moo 还没有被调用,它可能会在执行到 else 子句之前被调用。一旦进入else子句,函数moo的状态就和上一段一样了(无法确定)。
根据@Maxim 编辑的 link http://en.cppreference.com/w/cpp/atomic/memory_order link,上面的 memory_order_seq_cst.The 文本与 memory_order_acq_rel 交换时存在错误. memory_order_seq_cst 的文本:
memory_order_seq_cst:这个内存顺序的load操作执行acquire操作,store执行release操作,read-modify-write同时执行acquire操作和release操作,加单总存在所有线程以相同顺序观察所有修改的顺序(参见下面的 Sequentially-consistent 排序)
所以在你的例子中,存储操作等同于释放,这意味着 moo() 可以在栅栏之前重新排序。