atomic_compare_exchange_XXX
機能は、彼らの観測値と引数を「期待」を更新:
expected = current;
do {
desired = f(expected);
} while (!current.atomic_compare_exchange_weak(expected, desired));
希望の値が期待値の独立しであれば、このループは次のようになります。
desired = ...;
expected = current;
while (current.atomic_compare_exchange_weak(expected, desired))
;
いくつかのセマンティクスを追加しましょう。複数のスレッドがこれを同時に実行しているとします。いずれの場合も、desired
は現在のスレッドのゼロ以外のIDであり、current
は、相互排他を提供して、スレッドによってクリーンアップタスクが実行されることを保証します。どのスレッドが本当に気にする必要はありませんが、一部のスレッドがアクセス権を取得していることを確認する必要があります(そして、おそらく他のスレッドはcurrent
からIDを読み取って勝者を観察できます)。
我々は所望のセマンティクスを達成することができる:偽の障害が可能であるので、これは、atomic_compare_exchange_weak
がatomic_compare_exchange_strong
と同様の効果を達成するためにループを必要とする場合である
expected = 0;
if (current.atomic_compare_exchange_strong(expected, this_thread)) {
// I'm the winner
do_some_cleanup_thing();
current = 0;
} else {
std::cout << expected << " is the winner\n";
}
:
expected = 0;
while(!current.atomic_compare_exchange_weak(expected, this_thread)
&& expected == 0))
;
if (expected == this_thread) {
do_some_cleanup_thing();
current = 0;
} else {
std::cout << expected << " is the winner\n";
}
この標準では、実装では、..._weak
(§29.6.5/ 25 [atomics.types.operations.req])のループよりも、atomic_compare_exchange_strong
の方がより効率的なコードを提供する可能性があります。
操作が重要でないときはいつでもこのようになる可能性があります。彼らがしているいくつかの定期的な作業を持っているワーカースレッドがいくつかあるとしますが、キュー内の追加作業もチェックしています。 CASの操作によってキューがロックできないように見える場合、作業者は引き続き通常の作業を行うことができるため、大きな問題ではありません。 –