9

C++11 には、 と の 2 つのアトミック CAS 操作がありatomic_compare_exchange_weakますatomic_compare_exchange_strong

cppreferenceによると:

関数の弱い形式は偽って失敗することが許可されています。比較交換がループしている場合、一部のプラットフォームでは弱いバージョンの方がパフォーマンスが向上します。弱い比較交換にはループが必要で、強いものには必要ない場合は、強いものをお勧めします。

以下は、弱いバージョンを使用するための例です。

do {
    expected = current.value();
    desired = f(expected);
} while (!current.atomic_compare_exchange_weak(expected, desired));

強力なバージョンが望ましいように、比較と交換がループに入っていない例を誰かが挙げてもらえますか?

4

1 に答える 1

10

関数は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一部のスレッドが確実にクリーンアップ タスクを実行するように相互排除を提供するために使用されます。どのスレッドかはあまり気にしませんが、一部のスレッドが確実にアクセスできるようにしたいと考えています (また、他のスレッドが から ID を読み取って勝者を監視できる可能性もありますcurrent)。

以下を使用して、目的のセマンティクスを実現できます。

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";
}

これは、偽の障害が発生する可能性があるためatomic_compare_exchange_weak、 と同じ効果を達成するためにループが必要になるケースです。atomic_compare_exchange_strong

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";
}

atomic_compare_exchange_strong標準では、この場合、forでループするよりも実装がより効率的なコードを提供する可能性があることが示唆されています..._weak(§29.6.5/25 [atomics.types.operations.req])。

于 2013-07-29T01:47:41.743 に答える