C 11 CAS を使用した ABA カウンタの実装
ABA の問題は、メモリ位置の値が 2 回変更され、途中で設定された変更が行われた場合に発生します。元の値に戻ります。これにより、アトミック コンペア アンド スワップ (CAS) 操作に依存するスレッドが、実際には値が変更されていないにもかかわらず、値が変更されていないと信じ込ませる可能性があります。
ABA 問題を防ぐための一般的な解決策は、以下を作成することです。メモリ位置が変更されるたびに増加するカウンタ。このカウンターは、変更とともにアトミックにインクリメントされるため、CAS 操作は、カウンターが最後の操作以降に変更されたかどうかを確認できます。
C 11 では、std::atomic_compare_exchange_weak 関数がアトミック CAS 操作を提供します。ただし、値やカウンタなどの複数の変数を同時に変更することはできません。
C 11 CAS で ABA カウンタを実装するには、カウンタと値を隣接するメモリに保存する必要があります。これにより、単一の CAS 操作で両方の値をアトミックに更新できます。これは、2 つのメンバーを持つ構造体を使用して実現できます。最初のメンバーは値、2 番目のメンバーはカウンターです。
struct Node { std::atomic<int> value; std::atomic<int> counter; };
このデータ構造では、std::atomic_compare_exchange_weak 関数を使用して次のことを行うことができます。 ABA カウンタを実装します:
void modifyValue(Node& node, int newValue) { int expectedValue = node.value.load(std::memory_order_relaxed); int expectedCounter = node.counter.load(std::memory_order_relaxed); bool success; do { success = node.value.compare_exchange_weak(expectedValue, newValue, std::memory_order_acq_rel); success = node.counter.compare_exchange_weak(expectedCounter, expectedCounter + 1, std::memory_order_acq_rel); } while (!success); }
この例では、modifyValue 関数は最初に、 std::memory_order_relaxed メモリ順序。これにより、値が順序どおりに読み取られ、ティアリングが発生する可能性があります。
その後、std::atomic_compare_exchange_weak 関数を使用して、期待値とカウンターを現在の値と比較します。記憶の場所にあります。値が一致する場合、新しい値とカウンターは std::memory_order_acq_rel メモリ順序を使用してその場所に書き込まれます。これにより、操作の完了後に書き込みが他のスレッドに確実に表示されるようになります。
値が一致しない場合一致すると、compare_exchange_weak 関数は失敗し、ループが再度実行され、アトミック交換を再試行する前に最新の期待値とカウンターがロードされます。
この実装カウンタが値に応じてアトミックに増加することを保証し、ABA の問題を防ぎ、スレッドが値の一貫性に安全に依存できるようにします。
以上がアトミック比較アンドスワップを使用して C 11 で ABA カウンターを実装するにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。