这个java代码如何产生死锁?

我正在通过oracle文档进行死锁..我找到了这段代码

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.bowBack(this)在bower对象上调用时,它是否会将其锁定在alphonse对象上? 因为如果它保留了它的锁,那么在alphonse离开它之前,另一个对象上的bow函数将不会被锁定,并且它永远不会是死锁情况。

如果在打印第一行之后并且在调用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(); } } 

你有2个对象,alphonse和gaston以及2个线程,Thread1和Thread2

假设发生这种情况:

  1. Thread1:alphonse进入bow()方法。 并将锁定alphonse对象

  2. Thread2:gaston进入bow()方法。 并将锁定gaston对象

  3. Thread1:alphonse而在bow()方法中,在gaston对象上调用bowBack()。

    – > Thread1将阻塞,因为Thread2已经锁定了gaston

  4. Thread2:gaston在bow()方法中,在alphonse对象上调用bowBack()。

    – > Thread2将阻塞,因为Thread1已经锁定了alphonse

所以现在Thread1正在等待Thread2。 而Thread2正在等待Thread1。 这是一个僵局。

当您处理multithreading时,两个线程中的操作可以相对于彼此以任何顺序发生。 所以想象两个演员在这种情况下执行bow ,然后他们都试图执行bow_back 。 由于bowbow_back是同步的,因此两个对象都将被锁定,您将无法对其中任何一个执行bow_back 。 两个物体将一直等到另一个物体“自由”,并且这不会发生,因为在“鞠躬”之前bow不会返回。

如果两者同时或在期间进入bow()方法,则会发生交易

 System.out.println(); 

如果你没有看到两个“已向我鞠躬!” 消息,然后发生死锁!

如果第一个线程在第二个线程开始之前终止,则不会出现死锁。

使用Thread.sleep(1000)扩展代码;

 public synchronized void bow(Friend bower) { System.out.println(....); Thread.sleep(1000); ... } 

然后两个线程都进入bow()并且会发生dealock。

在弓A和G结束时召唤弓箭,导致从A的一个G.bow和来自G的A.bow的召唤,而A和G的弓是同步的。 所以他们都等着彼此完成。