public static void main(String[] args) {
final Friend aaa = new Friend("AAA");
final Friend bbb = new Friend("BBB");
new Thread(new Runnable() {public void run() { aaa.push(bbb); }}).start();
new Thread(new Runnable() {public void run() { bbb.push(aaa); }}).start();
}
static class Friend {
private final String name;
public Friend(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
public synchronized void push(Friend friend) {
for (int i = 0; i < 3; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {}
System.out.format(i + " - %s: %s" + " pushed me!%n", this.name, friend.getName());
}
friend.pushBack(this);
}
public synchronized void pushBack(Friend bower) {
System.out.format("%s: %s" + " pushed back to me!%n",this.name, bower.getName());
}
}
0 - AAA: BBB pushed me!
0 - BBB: AAA pushed me!
1 - BBB: AAA pushed me!
1 - AAA: BBB pushed me!
2 - AAA: BBB pushed me!
2 - BBB: AAA pushed me!
我的理解是synchronized方法只允许一个线程同时运行,那为什么打印结果是这样的呢?我认为bbb应该先等待aaa完成push方法。
为什么会因为同步方法pushBack而发生死锁?
出现死锁的原因是因为你的两个线程正在互相等待。
流程如下:
push
上调用 AAA
。它获取了 AAA
上的锁。push
上调用 BBB
。它获取了 BBB
上的锁。pushBack
上调用 BBB
。它尝试获取 BBB
上的锁,但线程 2 仍然拥有该锁。pushBack
上调用 AAA
。它尝试获取 AAA
上的锁,但线程 1 仍然拥有该锁。线程 1 现在正在等待线程 2 持有的锁,而线程 2 现在正在等待线程 1 持有的锁。两者都不会释放其锁,因此出现死锁。
在这种流程中,您的代码想要以不同的顺序获取一个或多个对象的锁,这是导致死锁的最常见原因之一。在大多数情况下,解决方案是使用固定顺序。