SCJP6手册中提供了以下代码
class ThreadA {
public static void main(String [] args) {
ThreadB b = new ThreadB();
b.start();
synchronized(b) {
try {
System.out.println("Waiting for b to complete...");
b.wait();
} catch (InterruptedException e) {}
System.out.println("Total is: " + b.total);
}
}
}
class ThreadB extends Thread {
int total;
public void run() {
synchronized(this) {
for(int i=0;i<100;i++) {
total += i;
}
notify();
}
}
}前面的代码会不会导致死锁,因为线程a和b都在b上有一个锁(在各自的同步块中)?
我遗漏了一些东西,但不太确定是什么。
发布于 2013-03-29 19:05:09
那得看情况。
来自wait方法的文档-
会导致当前线程等待,直到另一个线程为此对象调用notify()方法或notifyAll()方法。换句话说,这个方法的行为就像它简单地执行调用等待(0)一样。
当前线程必须拥有此对象的监视器。线程释放此监视器的所有权并等待,直到另一个线程通过调用notify方法或notifyAll方法通知等待此对象的监视器的线程唤醒。然后线程等待,直到它可以重新获得监视器的所有权并恢复执行。
所以,如果你考虑两种情况-
ThreadA首先获得对象b上的锁,它将等待,从而导致锁被释放,这将导致ThreadB继续其工作。ThreadB首先获得锁,那么它将继续其工作,释放锁,然后ThreadA将启动。接下来,ThreadA将等待对象锁b,这可能导致它永远等待。发布于 2013-03-29 19:05:17
最有可能的执行如下:
b.start()和正在执行的run方法之间有一个轻微的延迟b上的锁并进入synchronized块<代码>H19,然后等待<代码>D10(<代码>E111开始执行<代码>D15),监视器可用(或将很快可用),因此它可以进入<代码>D16块<代码>H217<代码>H118完成后,它通知D19可以停止等待<代码>H220<代码>H121主线程完成。<代码>H222<代码>F223
但是,根据线程调度的不同,不可能先执行run,在这种情况下,主线程可能会在b.wait()上永远等待。例如,如果你通过在b.start()后面插入一个小的Thread.sleep(100)来帮助解决这种情况,你应该观察这种行为。
底线:这是一个臭气熏天的代码,可能会遇到活跃性问题(它本身不是死锁,因为锁是可用的)。
https://stackoverflow.com/questions/15701930
复制相似问题