アトミック読み取り-変更-書き込みはアトミックまたは分離可能な操作ですか?
アトミック読み取り-変更-書き込み (RMW) 操作などx.exchange() は、メモリ位置の読み取りと書き込みの両方を行うアトミック操作であり、読み取り操作と書き込み操作が順番に実行されることを保証します。ただし、これらの操作が単一のアトミック操作とみなされるか、取得ロードとリリース ストアの組み合わせとみなされるかは、明示的に定義されていません。
標準の観点
よりC 標準の観点からは、RMW 操作は単一の操作とみなされます。これは、単一の名前 (RMW) があり、標準では単一の操作として参照されるという事実から明らかです。たとえば、[N4860](https://isocpp.org/files/papers/n4860.pdf) (ドラフトワーキングペーパー std::memory_order) には次のように記載されています。
「これによる読み取り、変更、書き込み操作メモリの順序は取得操作と解放操作の両方です。現在のスレッドでのメモリの読み取りまたは書き込みは、この前後に並べ替えることはできません。 store."
アトミック操作と分離可能な操作
アトミック操作と分離可能な操作の区別は、他の操作とどのように相互作用するかを決定するため重要です。 RMW 操作がアトミックとして扱われる場合、それは他のメモリ アクセスに関して順序を変更できないことを意味します。ただし、分離可能として扱われる場合、操作のロード コンポーネントとストア コンポーネントの間で順序を変更できる可能性が広がります。
サンプル コード
次のコード例を考えてみましょう。これは、x.exchange() と y.store() を使用して、2 つのアトミック変数 x と の値を設定します。 y.
std::atomic<int> x, y; void thread_A() { x.exchange(1, std::memory_order_acq_rel); y.store(1, std::memory_order_relaxed); } void thread_B() { int yy = y.load(std::memory_order_acquire); int xx = x.load(std::memory_order_acquire); std::cout << xx << ", " << yy << std::endl; }
x.exchange() が単一のアトミック操作として扱われる場合、操作のロード コンポーネントとストア コンポーネントを並べ替えることはできないことを意味します。したがって、スレッド B は、x と y の値が両方とも 1 であるか、両方とも 0 であることを常に監視します。
ただし、x.exchange() が分離可能として扱われる場合、ロードとストアが行われる可能性が残されます。操作のコンポーネントは並べ替えられる可能性があります。この場合、x からのロードが y にストアされる前に並べ替えられる可能性があるため、スレッド B は x と y の値が 0、1 になる可能性があります。
コンパイラの実装と標準解釈
標準の観点に基づくと、スレッド B は 0、1 を観察すべきではないように見えます。コードの ARM64 実装では、RMW 操作が分離可能として扱われ、ロード コンポーネントとストア コンポーネント間の並べ替えの可能性が考慮されることが示唆されています。
この明らかな矛盾により、cppreference の引用が間違っているのか、それとも単に標準の誤解なのかという疑問が生じます。 cppreference の引用は完全に正確ではない可能性がありますが、RMW 操作を単一のアトミック操作として扱う標準の一般的な扱いと一致しています。
標準では、次のような RMW 操作の動作を明示的に定義していないことに注意することが重要です。あらゆる状況。特に、同期との関係が RMW 操作にどのように適用されるかについての明確なガイダンスは提供されていません。そのため、RMW 操作には異なる解釈と実装の余地がある可能性があります。
以上がアトミックな読み取り、変更、書き込みは単一のアトミック操作ですか、それとも分離可能な操作ですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。