スプリアスウェイクアップのTL; DR仮定(「契約」)は、スレッドシェラーの現実的に堅牢な実装を可能にするために行われた、賢明なアーキテクチャ上の決定です。
「パフォーマンスに関する考慮事項」はここでは無関係であり、これらは公開された信頼できる参考文献で述べたために広まった誤解にすぎません。(信頼できる参照にはエラーがあるかもしれません- ガリレオ・ガリレイに聞いてください) Wikipediaの記事は引用されたメモへの参照を保持しています。
スプリアスウェイクアップの概念を導入するより説得力のある理由は、SOのこの回答で提供されており、その記事の(以前のバージョン)で提供された追加の詳細に基づいています。
スプリアスウェイクアップに関する Wikipediaの記事には、次のようなヒントがあります。
pthread_cond_wait()
Linux の機能は、futex
システムコールを使用して実装されます。Linux上の各ブロッキングシステムコールはEINTR
、プロセスがシグナルを受信すると突然戻ります。... システムコールのpthread_cond_wait()
外にあったわずかな時間で実際のウェイクアップを見逃す可能性があるため、待機を再開できませんfutex
...
考えてみてください...他のコードと同様に、スレッドスケジューラは、基盤となるハードウェア/ソフトウェアで異常が発生したために一時的なブラックアウトが発生する場合があります。もちろん、これが可能な限りまれに発生するように注意する必要がありますが、100%堅牢なソフトウェアなどはないため、これが発生すると想定し、スケジューラがこれを検出した場合にグレースフルリカバリに注意することは合理的です(例:欠落しているハートビートを観察することにより)。
さて、ブラックアウト中に待機中のスレッドに通知するためのシグナルを逃す可能性があることを考慮して、スケジューラはどのように回復できますか?スケジューラが何もしないと、「不運な」スレッドがハングし、永遠に待機します-これを避けるために、スケジューラはすべての待機スレッドにシグナルを送信します。
このため、待機中のスレッドに理由なく通知できる「契約」を確立する必要があります。正確には、スケジューラブラックアウトという理由がありますが、スレッドは(正当な理由で)スケジューラの内部実装の詳細を無視するように設計されているため、この理由は「スプリアス」として提示する方が適切です。
スレッドの観点からは、これはややポステルの法則(別名ロバスト性原理)に似ています。
あなたがすることにおいて保守的であり、他人から受け入れることにおいて寛大であること
スプリアスウェイクアップの仮定は、スレッドが行うことで保守的になります:他のスレッドに通知するときに条件を設定し、受け入れることでリベラルになります:待機から戻ったときに条件を確認し、まだない場合は待機を繰り返します。