みんなの「教えて(疑問・質問)」にみんなで「答える」Q&Aコミュニティ

こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

wait()したスレッドが起こされるタイミング

以下のコードにおいて。

% java ThreadWaitTest 2
の場合はaと表示したまま止まりますが、
% java ThreadWaitTest 1
の場合はスレッドの終了に伴ってwait()が切れ、bまで表示します。
私の望む動作は前者です。

後者の場合、これはつまりスレッドをwaitした際の待機プールがスレッドオブジェクトの場合、そのスレッドの実行が終了すると待機プールにある待機スレッドを自動でnotify()してしまうことを意味していると思うのですが、この解釈はあっていますか?

Java のAPIドキュメントに

「別のスレッドが notify メソッドまたは notifyAll メソッドを呼び出してこのオブジェクトのモニター上で待機するスレッドに通知を出すまで待機します」

とあるように、ユーザが明確的にnotifyしないと起こらないと思いこんでいました。

なぜこういう仕様になっているのでしょうか?
また、この仕様について詳しく書いてあるサイトやドキュメントなどありませんでしょうか?

public class ThreadWaitTest extends Thread {

 public Object mutex = new Object();
 
 public static void main(String[] args) {
  try {
   ThreadWaitTest test = new ThreadWaitTest();
   test.start();

   System.out.println("a");

   switch (new Integer(args[0])) {
   case 1:
    synchronized(test) {
     test.wait();
    }
    break;
   case 2:
    synchronized(test.mutex) {
      test.mutex.wait();
    }
    break;
   }

   System.out.println("b");

  } catch (InterruptedException ie) {
   ie.printStackTrace();
  }
 }

 public void run() {
  try {
   Thread.sleep(5000);
  } catch (InterruptedException ie){
   ie.printStackTrace();}
  }
}

投稿日時 - 2007-05-30 21:43:50

QNo.3043827

すぐに回答ほしいです

質問者が選んだベストアンサー

自信なし。
---

"spruious wakeup"みたいですが・・・。
("spurious wakeup"については、
「1.5以降のjavadocのObject#wait(long)の項」、
または
「Effective Java 項50」
などに簡単に記されている)

(今のところ)仕様とはされてないが、
現実には認知されている現象、というところだと思います。
---

"spurious wakeup"については、よく知らないので、
ネットで検索したり、
sunの「Bug Database」などで検索してみてください。
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4777391

投稿日時 - 2007-05-31 17:11:09

お礼

ご回答ありがとうございます。
wait()しか使っていなかったので、wait(long)の方に目を通していませんでした。

私が遭遇した「スレッドの終了時、そのスレッドオブジェクトの待機プールにある待機スレッドがnotify()される」という現象は spruious wakeup の一例に過ぎないのですかね。

ドキュメントに 稀に生じる と書いてあるところも怖いところです。

投稿日時 - 2007-06-01 06:16:24

このQ&Aは役に立ちましたか?

0人が「このQ&Aが役に立った」と投票しています

回答(2)

ANo.1

JDKにはそれらしい記述がありませんでしたね。

推測ですが、Threadが一度start()し、その後停止状態に遷移した場合、そのスレッドは二度とstart()できません。
もしnotify()を呼ぶ役目がそのThreadに課せられていたとしたら、二度とwait()状態から戻れない可能性もあるわけです。

ですので、「無効なオブジェクト」と化したThreadクラスは、その直前にnotifyAll()でもしているんじゃないでしょうか?

投稿日時 - 2007-05-30 22:54:29

お礼

ご回答ありがとうございます。

>「無効なオブジェクト」と化したThreadクラスは、その直前にnotifyAll()でもしているんじゃないでしょうか?

うむむ、なるほど。
しかしこの現象をみつけるまで、プログラムのバグを特定できずえらい時間がかかってしまいました。

投稿日時 - 2007-06-01 06:09:53

あなたにオススメの質問