4

次の状況があるとします。

synchronized void someMethod() {
    ...
    try {
       wait();
    }catch(InterruptedException e) {
       System.out.println("InterruptedException caught");
    } 
    ...
}

synchronized void someOtherMethod() {
    ...
    notify();  
}

そして、Thread最初にアクセスsomeMethodし、入っwaitてからsomeOtherMethod通知し、状態に戻りますRunnablenotify()メソッド内の呼び出しの位置は重要ですか? notify()メソッド内の別の位置に呼び出しを配置し​​ても、動作に変化はありませんでした。

Threadへの呼び出しが行われるとすぐに通知されるべきではありませんnotify()か?

4

3 に答える 3

5

ブロックnotify()内の呼び出しの位置は重要ではありませ。定義上、まだブロック内にいる場合は、ロックを保持しているからです。synchronizedsynchronized

notify() の呼び出しが行われるとすぐにスレッドに通知されるべきではありませんか?

はい。呼び出しnotify()により、スレッドの 1 つ (存在する場合) が待機キュー (条件を待っている) からブロックされたキュー (ロックを待っている) に入れられます。これはすぐに行われますが、起動されたスレッドは実行を開始する前にロックを取得する必要があります。そのため、すぐに待機キューから移動されますが、ロックを取得するためにまだ待機しています。

ところで、どのオブジェクトが影響を受けているかを明示するために、これを次this.wait()のように書くことをお勧めします。this.notify()

于 2012-07-18T15:32:55.123 に答える
2

いいえ、同期ブロック内の notify() 呼び出しの位置は関係ありません。

私はスタイルをお勧めします:

class SomeClass {
  synchronized void someMethod() throws InterruptedException{
    ...
    while (! someCondition) {
      wait();
    } 
    ...
  }

  synchronized void someOtherMethod() {
    ...
    makeConditionValid();
    notifyAll();  
  }
}

呼び出しwhileの周りにループが使用されていることに注意してください。wait一部の JVM は誤った通知を発行する可能性があるため、スレッドが通知されたときに、スレッドを待機させた元の状態が有効であるという保証はありません。また、起動されたスレッドは、通知スレッドがロックを解放するまで実行されません。そのため、待機中のスレッドが実行されるまでに、条件が再び無効になる可能性があります。

于 2012-07-18T15:47:32.353 に答える
0

これらの呼び出し (すなわちObject#waitおよびObject#notify) は、同期ブロック内で行う必要があります。メソッドが同期されているため、同期ブロックのスコープにはメソッド内のすべてが含まれます。したがって、ポジショニングは関係ありません。

于 2012-07-18T15:36:12.963 に答える