cppreference.comのドキュメントstd::memory_order
には、緩和された順序付けの例があります。
ゆるやかな注文
タグ付けさ
memory_order_relaxed
れたアトミック操作は同期操作ではありません。同時メモリアクセスに順序を課すことはありません。原子性と変更順序の一貫性のみが保証されます。たとえば、xとyが最初はゼロの場合、
// Thread 1: r1 = y.load(std::memory_order_relaxed); // A x.store(r1, std::memory_order_relaxed); // B // Thread 2: r2 = x.load(std::memory_order_relaxed); // C y.store(42, std::memory_order_relaxed); // D
は、r1 == r2 == 42を生成することを許可されています。なぜなら、Aはスレッド1内でBの前にシーケンスされ、Cはスレッド2内でDの前にシーケンスされるからです。 xの変更順序でCの前に表示されます。yに対するDの副作用はスレッド1の負荷Aに見え、xに対するBの副作用はスレッド2の負荷Cに見える可能性があります。特に、これはDがCの前に完了する場合に発生する可能性があります。スレッド2、コンパイラの並べ替えまたは実行時のいずれかが原因。
「Cはスレッド2内でDの前にシーケンスされます」と書かれています。
評価順にあるsequenced-beforeの定義によれば、AがBの前にシーケンス化されている場合、Aの評価はBの評価が始まる前に完了します。Cはスレッド2内でDの前に順序付けられているため、Dが始まる前にCを完了する必要があるため、スナップショットの最後の文の条件部分は決して満たされません。