0

私は2つのスレッドthread1とthread2を持っています

スレッド1内

synchronized(lock) {  
    lock.wait();  
    if(lock == null)
        {execute1}  
    if(lock != null)  
        {execute2}   
}  

スレッド2内

synchronized(lock) {  
    lock.notify();  
    lock = null;  
}  

最初にスレッド 1 が呼び出され、次にスレッド 2 が呼び出されます。
thread1 が wait を呼び出した後、ロックを解放します。そしてスレッド 2 は通知を呼び出し、ロックを null に設定します。
スレッド 1 が再びロックを取得しようとすると、例外がスローされないのはなぜですか。lock が null に設定されており、thread1 がそのロックを取得しようとするため、ロックを取得しようとしたときに null ポインター例外をスローするべきではありません。
例外がスローされない場合、thread1 はまだ null ではないロック値を読み取っています。では、ステートメント {execute2} を実行するべきではありませんか?

4

1 に答える 1

1

変数ではなくオブジェクトで同期します。モニターはオブジェクトに属します。

lock が null 以外のオブジェクトを指していて、それを待っている場合、null に設定lockても意味がありません。これは、 lock が指すオブジェクトが待機され、通知されたためです。lock

次に、変数がその時点で null であるため、スレッド 1 が制御を取り戻すと、execute1 が呼び出されます。

編集

全体wait()とセマンティクスを誤解しているように見えるので、Javadocnotify()からの関連する引用を次に示します(私の強調):

現在のスレッドは、このオブジェクトのモニターを所有している必要があります。スレッドは、このモニターの所有権を解放し、別のスレッドが、このオブジェクトのモニターで待機しているスレッドに、notify メソッドまたは notifyAll メソッドの呼び出しによってウェイクアップを通知するまで待機します。スレッドは、モニターの所有権を再度取得できるまで待機し、実行を再開します。

これは、変数が、同期/待機/通知するオブジェクトを指すために使用された後は完全に無関係であることを示しているはずです。

于 2012-04-18T16:49:08.467 に答える