ブーストスレッドでの偽のブロック解除
-
05-07-2019 - |
質問
void wait(boost::unique_lock<boost::mutex>& lock)
...
効果:原子的にlock.unlock()を呼び出す 現在のスレッドをブロックします。の スレッドは、通知を受けたときにブロックを解除します this-&gt; notify_one()または this-&gt; notify_all()、または誤って。 スレッドがブロック解除されたとき( 何らかの理由で)、ロックは lock.lock()を呼び出して再取得します 待機呼び出しが戻る前。の ロックは、呼び出しによっても再取得されます lock.lock()関数が終了する場合 例外。
だから私が興味を持っているのは、「偽りの」という言葉の意味です。偽の理由でスレッドのブロックが解除されるのはなぜですか?これを解決するために何ができますか?
解決
アンソニーウィリアムズによるこの記事は特に詳細です。 。
スプリアスウェイクは予測できません。 それらは本質的にランダムです ユーザーの視点。しかし、彼らは スレッドライブラリが 確実に待機することを保証できない スレッドは通知を見逃しません。 通知を逃すと 条件変数を役に立たなくする、 スレッドライブラリはスレッドを呼び起こします 待つよりもその待機から リスク。
また、持続時間を要する timed_wait
オーバーロードを使用すべきではなく、通常、述語をとるバージョンを使用する必要があることも指摘しています
これは初心者のバグであり、 それは簡単で簡単に克服できます ルール:常に述語をチェックします 条件付きで待機中のループ 変数。もっと陰湿なバグが来る timed_wait()から。
Vladimir Prusによるこの記事も興味深いものです。
>しかし、なぜwhileループが必要なのですか、 書くことはできません:
if (!something_happened)
c.wait(m);
できません。そして、キラーの理由は、「待つ」ことができるということです 「通知」呼び出しなしで戻ります。 それはスプリアスウェイクアップと呼ばれ、 POSIXによって明示的に許可されています。 基本的に、「待機」からのみ戻る 共有データが 変更されたため、データは 再度評価しました。
さて、なぜこれがまだ修正されていないのですか? 最初の理由は誰も望んでいないことです それを修正します。呼び出しを「待機」にラップ ループはいくつかのために非常に望ましいです 他の理由。しかし、それらの理由 説明が必要ですが、偽りがあります ウェイクアップは適用できるハンマーです なしの最初の1年生へ 失敗します。
他のヒント
このブログ投稿は、Linuxの理由を言葉で示していますシグナルがプロセスに配信されたときに戻る futex
システムコールの残念ながら、それは他のことを何も説明していません(そして実際、さらなる情報を求めています)。
偽のウェイクアップに関するウィキペディアのエントリ(posix全体の概念のように見えますが、ちなみに、ブーストに限定されるものではありません)あなたにも興味があります。