さまざまなロック関連の質問を見て、(ほぼ)常に「スプリアスウェイクアップによるループ」の用語を見つける1 誰かがそのような種類のウェイクアップを経験したことがあるのだろうか(たとえば、まともなハードウェア/ソフトウェア環境を想定)?
「スプリアス」という用語は明白な理由を意味しないことを知っていますが、そのようなイベントの理由は何ですか?
(1 注:ループの練習については質問していません。)
編集:ヘルパーの質問(コードサンプルが好きな人向け):
次のプログラムがあり、それを実行する場合:
public class Spurious {
public static void main(String[] args) {
Lock lock = new ReentrantLock();
Condition cond = lock.newCondition();
lock.lock();
try {
try {
cond.await();
System.out.println("Spurious wakeup!");
} catch (InterruptedException ex) {
System.out.println("Just a regular interrupt.");
}
} finally {
lock.unlock();
}
}
}
ランダムなイベントを永遠に待たずに、このawait
を誤って起動するにはどうすればよいですか?
ウィキペディア スプリアスウェイクアップに関する記事 には次のようなヒントがあります:
Linuxの
pthread_cond_wait()
関数は、futex
システムコールを使用して実装されます。 Linux上の各ブロッキングシステムコールは、プロセスがシグナルを受信すると、EINTR
で突然戻ります。 ...pthread_cond_wait()
は、futex
システムコールの外部にあったわずかな時間で実際のウェイクアップを見逃す可能性があるため、待機を再開できません。この競合状態は、呼び出し側が不変式をチェックすることによってのみ回避できます。したがって、POSIX信号はスプリアスウェイクアップを生成します。
要約:Linuxプロセスにシグナルが送られた場合、待機中のスレッドはそれぞれナイス、ホットスプリアスウェイクアップを楽しみます 。
それを買います。これは、よくあるあいまいな「パフォーマンスのため」の理由よりも、飲みやすい錠剤です。
この動作を示す生産システムがあります。スレッドは、キューにメッセージがあるというシグナルを待ちます。繁忙期には、最大20%のウェイクアップがスプリアスです(つまり、ウェイクアップ時にキューに何もありません)。このスレッドは、メッセージの唯一のコンシューマです。 Linux SLES-10 8プロセッサボックスで実行され、GCC 4.1.2で構築されています。システムが十分に速くメッセージを読み取れない場合は問題があるため、メッセージは外部ソースから送信され、非同期で処理されます。
タイトルの質問に答えるために-はい!それは起こります Wiki記事 は偽の目覚めについてかなり言及しています私が出会ったのと同じものの素敵な説明は次のとおりです-
考えてみてください...他のコードと同様に、スレッドスケジューラは、基盤となるハードウェア/ソフトウェアで異常が発生したために一時的なブラックアウトが発生する場合があります。もちろん、これが可能な限りまれに発生するように注意する必要がありますが、100%堅牢なソフトウェアなどは存在しないため、これが発生すると想定し、スケジューラがこれを検出した場合にグレースフルリカバリに注意することは合理的です(例:失われたハートビートを観察することにより)。
では、ブラックアウト中に待機中のスレッドに通知するためのシグナルを逃す可能性があることを考慮して、スケジューラはどのように回復できますか?スケジューラが何もしないと、「不運な」スレッドがハングし、永遠に待機します。これを回避するために、スケジューラはすべての待機スレッドにシグナルを送信します。
このため、待機中のスレッドに理由なく通知できる「契約」を確立する必要があります。正確には、スケジューラブラックアウトという理由がありますが、スレッドは(正当な理由で)スケジューラの内部実装の詳細を無視するように設計されているため、この理由は「スプリアス」として提示する方が適切です。
Source からこの回答を読んでいて、十分に妥当であることがわかりました。また読む
Javaおよびそれらを回避する方法)でのスプリアスウェイクアップ 。
PS:上記のリンクは、スプリアスウェイクアップに関する追加の詳細が記載されている私の個人ブログです。
Cameron Purdy を書きました ブログ投稿 しばらく前に、スプリアスウェイクアップの問題に見舞われました。はい、そうです
Javaがデプロイされるプラットフォーム??が間違っているかもしれませんが、いくつかのプラットフォームの制限のために、(可能性として)仕様にあると推測しています!
これを追加するだけです。はい、発生し、24コアマシン(JDK 6)でマルチスレッドの問題の原因を検索するのに3日間を費やしました。 10回の実行のうち4回がパターンなしでそれを経験しました。これは、2コアまたは8コアでは発生しませんでした。
オンライン資料をいくつか調べましたが、これはJavaの問題ではなく、一般的にまれですが予想される動作です。
https://stackoverflow.com/a/1461956/14731 には、基になるオペレーティングシステムがスプリアスウェイクアップをトリガーしない場合でも、スプリアスウェイクアップを防ぐ必要がある理由の優れた説明が含まれています。この説明は、Javaを含む複数のプログラミング言語に適用されることに注意してください。