jlh*_*jlh 9 java multithreading join notify wait
给出以下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()");
}
}
}
Run Code Online (Sandbox Code Playgroud)
运行它将等待一秒钟然后正确退出.但这对我来说意外,我预计会发生死锁.
我的推理如下:新创建的MyThread将执行run(),它被声明为'synchronized',因此它可以调用wait()并安全地读取'mustShutdown'; 在wait()调用期间,锁定被释放并在返回时重新获取,如wait()文档中所述.一秒钟后,主线程执行shutdown(),再次同步,以便在其他线程正在读取的同时不访问mustShutdown.然后它通过notify()唤醒另一个线程,并通过join()等待它的完成.
但在我看来,其他线程无法从wait()返回,因为它需要在返回之前重新获取线程对象上的锁.它不能这样做因为shutdown()在join()内部仍然保持锁定.为什么它仍能正常工作并正常退出?
join()方法在内部调用wait(),这将导致释放锁(Thread对象).
请参阅下面的join()代码:
public final synchronized void join(long millis)
throws InterruptedException {
....
if (millis == 0) {
while (isAlive()) {
wait(0); //ends up releasing lock
}
}
....
}
Run Code Online (Sandbox Code Playgroud)
你的代码看到这个并且一般看不到的原因:你的代码看到这个而不是一般没有观察到的原因是因为join()方法在Thread对象本身上等待()因此放弃对Thread对象的锁定本身,并且您的run()方法也在同一个Thread对象上同步,您会看到这种意外情况.