bool compare_exchange_weak (T& expected, T val, ..);
compare_exchange_weak()
C ++ 11で提供される比較交換プリミティブの1つです。それはだ、弱いオブジェクトの値が等しい場合、それは偽さえを返すという意味でexpected
。これは、(x86のように1つではなく)一連の命令を使用して実装する一部のプラットフォームでの誤った障害が原因です。このようなプラットフォームでは、コンテキストスイッチ、別のスレッドによる同じアドレス(またはキャッシュライン)のリロードなどにより、プリミティブが失敗する可能性があります。それはだspurious
、それが(等しくないオブジェクトの値ではありませんようexpected
、操作を失敗しました)。代わりに、それは一種のタイミングの問題です。
しかし、私を困惑させるのは、C ++ 11標準(ISO / IEC 14882)で言われていることです。
29.6.5 ..疑似障害の結果、弱いコンペアアンドスワップのほぼすべての使用がループになります。
ほぼすべての用途でループする必要があるのはなぜですか?それは、誤った失敗のために失敗したときにループすることを意味しますか?もしそうなら、なぜcompare_exchange_weak()
私たちは自分たちでループを使用して書くのですか?私たちはcompare_exchange_strong()
、私たちのために偽の失敗を取り除くべきだと私が思うものを使うことができます。の一般的な使用例はcompare_exchange_weak()
何ですか?
関連する別の質問。彼の著書「C ++ Concurrency In Action」の中で、Anthonyは次のように述べています。
//Because compare_exchange_weak() can fail spuriously, it must typically
//be used in a loop:
bool expected=false;
extern atomic<bool> b; // set somewhere else
while(!b.compare_exchange_weak(expected,true) && !expected);
//In this case, you keep looping as long as expected is still false,
//indicating that the compare_exchange_weak() call failed spuriously.
なぜ!expected
ループ状態にあるのですか?すべてのスレッドが飢えてしばらく進行しないのを防ぐためにありますか?
編集:(最後の質問)
単一のハードウェアCAS命令が存在しないプラットフォームでは、弱いバージョンと強いバージョンの両方がLL / SCを使用して実装されます(ARM、PowerPCなど)。では、次の2つのループに違いはありますか?なぜ、もしあれば?(私にとって、それらは同様のパフォーマンスを持つはずです。)
// use LL/SC (or CAS on x86) and ignore/loop on spurious failures
while (!compare_exchange_weak(..))
{ .. }
// use LL/SC (or CAS on x86) and ignore/loop on spurious failures
while (!compare_exchange_strong(..))
{ .. }
この最後の質問で、ループ内でパフォーマンスの違いがあるかもしれないと皆さんが言っています。また、C ++ 11標準(ISO / IEC 14882)でも言及されています。
コンペアアンドスワップがループしている場合、一部のプラットフォームでは、弱いバージョンの方がパフォーマンスが向上します。
しかし、上で分析したように、ループ内の2つのバージョンは、同じ/同様のパフォーマンスを提供するはずです。私が恋しいことは何ですか?