给定以下 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()");
}
}
}
运行此程序将等待一秒钟,然后正确退出。但这对我来说是出乎意料的,我预计这里会发生死锁。
我的推理如下:新创建的 MyThread 将执行 run(),它被声明为 'synchronized',这样它就可以调用 wait() 并安全地读取 'mustShutdown';在 wait() 调用期间,锁被释放并在返回时重新获取,如 wait() 文档中所述。一秒钟后,主线程执行shutdown(),它再次被同步,以便在另一个线程读取它的同时不访问mustShutdown。然后它通过 notify() 唤醒另一个线程并通过 join() 等待其完成。
但在我看来,其他线程永远不可能从 wait() 中返回,因为它需要在返回之前重新获取线程对象上的锁。它不能这样做,因为shutdown() 在join() 中仍然持有锁。为什么它仍然可以正常工作并正常退出?