:Java wait()/ join():これはデッドロックしないのはなぜですか?次のJavaコードを考える
public class Test {
static private class MyThread extends Thread {
private boolean mustShutdown = false;
@Override
public synchronized void run() {
// loop and do nothing, just wait until we must shut down
while (!mustShutdown) {
try {
wait();
} catch (InterruptedException e) {
System.out.println("Exception on wait()");
}
}
}
public synchronized void shutdown() throws InterruptedException {
// set flag for termination, notify the thread and wait for it to die
mustShutdown = true;
notify();
join(); // lock still being held here, due to 'synchronized'
}
}
public static void main(String[] args) {
MyThread mt = new MyThread();
mt.start();
try {
Thread.sleep(1000);
mt.shutdown();
} catch (InterruptedException e) {
System.out.println("Exception in main()");
}
}
}
1秒間待ってから、適切に終了しますこれを実行します。しかし、それは私にとって予期せぬことです。デッドロックがここで起こることを期待しています。
私の推論は次のとおりです:新しく作成されたMyThreadはrun()を実行します。これはwait()を呼び出し、安全に 'mustShutdown'を読み込むことができるように 'synchronized'として宣言されます。そのwait()呼び出しの間、wait()のドキュメントに記載されているように、ロックは解放され、戻ったときに再取得されます。 1秒後、メインスレッドはshutdown()を実行します。これはもう一方のスレッドが読み込んでいるのと同時に、mustShutdownにアクセスしないように再び同期します。その後、notify()を介してもう一方のスレッドを起動し、join()を介してその完了を待ちます。
私の意見では、戻る前にスレッドオブジェクトのロックを再取得する必要があるので、他のスレッドがwait()から戻ることはできません。 shutdown()はjoin()の内部でロックを保持しているので、これを行うことはできません。なぜそれはまだ動作し、正しく終了しますか?
このような副作用があるため、スレッドを直接拡張するため、直接眉をひそめます。スレッドでラップするRunnableを実装する必要があります。 –