2009-06-26 13 views
176

さまざまなロック関連の質問を見て、(ほとんど)常に偽の起床のためにループを見つける私はこのような種類の起床を経験したことがありますか?偽の起床は実際に起こりますか?

「スプリアス」という用語は明白な理由がないことを知っていますが、そのような種類のイベントの理由は何ですか?

(注:私はループの練習に疑問を投げかけていないよ)

編集:(コードサンプルを好きな人のための)ヘルパー質問:

私は、次のプログラムを持っている場合、と私はそれを実行します。

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を覚ますために何ができますか?

答えて

175

ウィキペディアarticle on spurious wakeupsこのちらほらがあります。Linuxで

pthread_cond_wait()機能はfutexシステムコールを使用して実装されています。プロセスがシグナルを受信すると、Linux上の各ブロッキングシステムコールは、EINTRで突然復帰します。 ... pthread_cond_wait()futexシステムコールの外に少しの時間で実際のウェイクアップを逃す可能性があるため、待機を再開できません。この競合状態は、呼び出し元が不変条件をチェックすることによってのみ回避できます。したがって、POSIX信号は偽のウェークアップを生成します。

概要:Linuxプロセスが待機しているスレッドを通知された場合、それぞれが素敵な、熱い見せかけの起動をお楽しみいただけます。

私はそれを購入する。それはしばしばあいまいである "それはパフォーマンスのためのもの"の理由よりも簡単に飲み込むことができます。

+11

ベター説明:http://stackoverflow.com/questions/1461913/does-c-monitor-wait-suffer-from-spurious-wakeups/1461956#1461956 – Gili

+3

このEINTRのブロック解除は、Unixの内のすべてのブロックシステムの真の呼び出しをされて導出システム。これによりカーネルはより簡単になりましたが、アプリケーションプログラマは負担を買っていました。 –

+1

私はpthread_cond_wait()と友人がEINTRを返すことができないと思っていましたが、擬似的に目を覚ますとゼロを返します。送信元: http://pubs.opengroup.org/onlinepubs/7908799/xsh/pthread_cond_wait.html "これらの関数は[EINTR]のエラーコードを返しません。" – gubby

8

Cameron Purdyは、blog postを書いていますが、間違った起床問題にぶつかっています。そう、はい、それは起こる

私はそれがJavaが展開されるいくつかのプラットフォームの制限のために(可能性として)仕様にあると思いますか?私は間違っているかもしれませんが!

+5

http://www.jroller.com/cpurdy/entry/java_supplies_apologies_to_weird – akarnokd

+0

私はこの記事を読んで、ランダムに/確定的に目を覚ますことによって、ループウェイトのパラダイムへのアプリケーションの適合性をテストする単体テストについて考えました。それとも既にどこかで利用可能ですか? – akarnokd

+0

これは別の質問です。 "テストに使用できる*厳密な* VMはありますか?"私は厳密なスレッドローカルメモリを持つものを見たいと思う - 彼らはまだ存在するとは思わない。 –

20

私はこの動作を示す実動システムを持っています。 スレッドは、キューにメッセージがあることを示す信号を待ちます。 忙しい時には、起床の20%までが偽です(起床したときには何もキューに入っていません)。 このスレッドはメッセージの唯一のコンシューマです。 Linux SLES-10 8プロセッサーボックスで動作し、GCC 4.1.2で構築されています。 メッセージは外部ソースから取得され、システムが十分速く読み取れない場合に問題が発生するため、非同期で処理されます。

7

これを追加するだけです。はい、それは起こり、3日間、24コアマシン(JDK 6)でマルチスレッド問題の原因を探しました。 10のうちの4つの処刑は、パターンなしでそれを経験した。これは決して2つのコアまたは8つのコアで発生しませんでした。

これはJavaの問題ではありませんが、一般的にはまれですが予想される動作です。

+0

こんにちはReneS、そこに走っているアプリを開発していますか? wait()メソッドは、Javaのドキュメントhttp://docs.oracle.com/javase/6/docs/api/java/lang/Object.html#で提案されているように、whileループの外部条件をチェックインしていますか? %28%を待つ29? – gumkins

+0

私はそれについて書きましたが、解決策は条件チェック付きのwhileループです。私の間違いは欠けていたループでした...しかし、私はこれらの目覚めについて学びました...決して2つのコアで、たいていは24coresではありませんhttps://blog.xceptance.com/2011/05/06/spurious-wakeup-the-rare -event / – ReneS

11

はtitileで質問に答えるために - はい!それはhappen.Though Wiki articleは、次のように私が出会ったのと同じのための素晴らしい説明があるスプリアスウェイクアップについての良い取引を言及しない -

はちょうどそれを考える...任意のコードのように、スレッドスケジューラに発生する可能性があります潜在的なハードウェア/ソフトウェアに何らかの異常が発生したために一時的にブラックアウトする。もちろん、これが可能な限り稀であるように注意する必要がありますが、100%の堅牢なソフトウェアはないので、スケジューラがこれを検出した場合の優雅な回復に注意してください。不足している心拍を観察することによって)。

さて、どのように停電時にそれがスレッドを待って通知することを目的といくつかの信号を逃す可能性があることを考慮に入れて、回復スケジューラだろうか?スケジューラが何もしない場合、「不運な」スレッドはちょうどハングし、永遠に待っています。これを避けるために、スケジューラはすべての待ちスレッドに信号を送ります。

これは、待機中のスレッドが理由なしに通知することができるという「契約」を確立することが必要になります。正確には、スケジューラのブラックアウトの理由がありますが、スレッドは内部実装の詳細をスケジューリングしないように設計されているため、この理由は「間違った」ものである可能性が高くなります。

私はSourceからこの回答を読んでいて、十分に妥当であることがわかりました。また、

Spurious wakeups in Java and how to avoid themをお読みください。

関連する問題