我正在通过oracle docs进行僵局。 我找到了这段代码
public class Deadlock {
static class Friend {
private final String name;
public Friend(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
public synchronized void bow(Friend bower) {
System.out.format("%s: %s"
+ " has bowed to me!%n",
this.name, bower.getName());
bower.bowBack(this);
}
public synchronized void bowBack(Friend bower) {
System.out.format("%s: %s"
+ " has bowed back to me!%n",
this.name, bower.getName());
}
}
public static void main(String[] args) {
final Friend alphonse =
new Friend("Alphonse");
final Friend gaston =
new Friend("Gaston");
new Thread(new Runnable() {
public void run() { alphonse.bow(gaston); }
}).start();
new Thread(new Runnable() {
public void run() { gaston.bow(alphonse); }
}).start();
}
}
我无法理解,在什么情况下会发生死锁?
我运行此代码,它运行正常。所以必须有一些特殊的事件,什么时候会发生死锁?
假设首先在alphonse
对象上调用bow,当在bower对象上调用alphonse
时它是否会锁定bower.bowBack(this)
对象?
因为如果它保留了它的锁定,那么在bow
保持锁定之前,另一个对象上的alphonse
函数将不会被锁定,并且它永远不会成为死锁情况。
答案 0 :(得分:4)
如果在打印第一行之后并且在调用bowBack之前放置了Thread.sleep(1000),则应该看到死锁。无论如何都会发生这种僵局,这种情况很少发生。
你有两个线程和两个被获取的锁是不同的命令。这可以使每个线程保持一个锁但无法获得第二个锁。即死锁。
注意:线程需要花费大量时间才能启动,这意味着第一个线程可以在第二个线程启动之前运行完成,因此您不太可能看到问题。
这是给你的益智游戏。这会造成僵局,你能明白为什么吗?
class A {
static final int i;
static {
i = 128;
Thread t = new Thread() {
public void run() {
System.out.println("i=" + i);
}
};
t.start();
try {
t.join();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
答案 1 :(得分:4)
你有2个对象,alphonse和gaston以及2个线程,Thread1和Thread2
假设发生这种情况:
Thread1:alphonse进入bow()方法。并将锁定alphonse对象
Thread2:gaston进入bow()方法。并将锁定gaston对象
Thread1:在bow()方法中使用alphonse,在gaston对象上调用bowBack()。
- > Thread1将阻塞,因为Thread2已经锁定了gaston
Thread2:gaston在bow()方法中,在alphonse对象上调用bowBack()。
- > Thread2将阻塞,因为Thread1已经锁定了alphonse
所以现在Thread1正在等待Thread2。而Thread2正在等待Thread1。这是一个僵局。
答案 2 :(得分:3)
当您处理多线程时,两个线程中的操作可能以任何顺序相互发生。因此,假设在这种情况下两个actor都执行bow
,然后他们都尝试执行bow_back
。当bow
和bow_back
同步时,两个对象都将被锁定,您将无法对其中的任何对象执行bow_back
。两个对象都会等到另一个对象“空闲”,这不会发生,因为bow
在它“退回”之前不会返回。
答案 3 :(得分:1)
如果两者同时或在
期间输入bow()
方法,则会发生交易
System.out.println();
如果你没有看到两个“已经向我退回!”消息,那么就会发生死锁!
如果第一个线程在第二个线程开始之前终止,则不存在死锁。
使用Thread.sleep(1000);
扩展代码public synchronized void bow(Friend bower) {
System.out.println(....);
Thread.sleep(1000);
...
}
然后两个线程都进入bow()并且会发生交易。
答案 4 :(得分:0)