ウィキペディアの記事によると Spurious Wakeups
「スレッドが条件変数を通知していなくても、スレッドが待機状態から目覚めている可能性があります。」.
この「機能」については知っていますが、同じ記事で実際に何が原因であるかはわかりませんでした。
「偽のウェイクアップは奇妙に聞こえるかもしれませんが、一部のマルチプロセッサシステムでは、条件のウェイクアップを完全に予測可能にすると、すべての条件変数の操作が大幅に遅くなる可能性があります。」
修正する価値がないバグのように聞こえますが、それは正しいですか?
TL; DR偽のウェイクアップの仮定(「契約」)は、スレッドシェデュラーの現実的に堅牢な実装を可能にするために行われた賢明なアーキテクチャ上の決定です。
「パフォーマンスに関する考慮事項」はここでは関係ありません。これらは、公表された信頼できるリファレンスに記載されているために広く普及した誤解です。 (権威ある参照にはエラーがあるかもしれません、知っています-ただ尋ねてください Galileo Galilei ) ウィキペディアの記事は、公開された参考文献を引用するという正式なガイドラインに完全に一致しているという理由だけで、引用したメモへの参照を保持しています。
偽のウェイクアップの概念を導入するためのはるかに説得力のある理由は SOでのこの回答 で提供されています。
ウィキペディア 偽のウェイクアップに関する記事 にはこの一言があります:
Linuxの
pthread_cond_wait()
関数は、futex
システムコールを使用して実装されます。 Linuxの各ブロッキングシステムコールは、プロセスがシグナルを受信すると、EINTR
で突然戻ります。 ...pthread_cond_wait()
は、futex
システムコールの外にあった少しの時間で実際のウェイクアップを見逃す可能性があるため、待機を再開できません...
考えてみてください...他のコードと同様に、スレッドスケジューラは、基盤となるハードウェア/ソフトウェアで異常が発生したために一時的にブラックアウトする可能性があります。もちろん、これができる限り発生しないように注意する必要がありますが、100%堅牢なソフトウェアなどは存在しないので、これは発生する可能性があると想定して注意する必要がありますスケジューラーがこれを検出した場合に備えて(たとえば、欠落しているハートビートを観察することによって)正常な回復。
では、ブラックアウト中に、待機中のスレッドに通知することを目的としたいくつかの信号を見逃す可能性があることを考慮して、スケジューラはどのように回復できますか?スケジューラが何もしない場合、言及された「不運な」スレッドはハングして永久に待機します。これを回避するには、スケジューラは待機中のすべてのスレッドにシグナルを送信します。
これにより、理由なしに待機中のスレッドに通知できる「契約」を確立する必要があります。正確には、理由があります-スケジューラーのブラックアウト-スレッドは(正当な理由で)スケジューラーの内部実装の詳細に気付かないように設計されているため、この理由は「偽物」として提示する方が良いでしょう。
スレッドの観点から見ると、これはポステルの法則(別名 ロバストネスの原則 )に多少似ています。
自分の行動を保守的にし、他人から受け入れることを寛大にする
スプリアスウェイクアップの仮定により、スレッドは強制的に保守的になります:他のスレッドに通知するときに条件を設定し、受け入れ可能なものには寛大です:待機から戻ったときに条件を確認し、まだない場合は待機を繰り返します。
競合状態に対処するために、呼び出し元のコードはとにかく同じ処理(状態のチェック)を使用する必要があるため、修正する価値はありません。
2つの問題に対する1つの扱い。これを以下に要約します。
スプリアスウェイクアップ:待機スレッドは、条件が確立される前にスケジュールされます。
後者が発生する可能性があるため、契約に偽のウェイクアップを導入することまで行った人もいます。