memory_order_seq_cst 如何与非原子操作同步?

Zet*_*eta 6 c++ multithreading synchronization atomic

如果使用单个原子变量 and std::memory_order_seq_cst,是否保证非原子操作不会被重新排序?

例如,如果我有

std::atomic<bool> quux = {false};

void foo() {
    bar();
    quux.store(true, std::memory_order_seq_cst);
    moo();
}
Run Code Online (Sandbox Code Playgroud)

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
}
Run Code Online (Sandbox Code Playgroud)

请注意,我假设既不使用bar也不moo使用原子操作、互斥锁、锁、栅栏或其他同步功能。

Max*_*kin 2

如果使用单个原子变量 和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()在调用 store 之后不会重新排序,并且moo()在调用 store 之前不会重新排序,只要我使用 std::memory_order_seq_cst ,至少从另一个线程的角度来看?

bar如果和的定义moo在当前翻译单元中不可用,则编译器假定这些函数会加载内存和/或具有副作用(执行 I/O 或存储到内存),因此无法围绕操作重新排序memory_order_seq_cst

如果定义可用并且函数不执行 I/O 或内存加载/存储,则可以对它们重新排序。这些将是纯函数或不执行任何操作并返回void常量的函数。