这个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
假设发生这种情况:
-
Thread1:alphonse进入bow()方法。 并将锁定alphonse对象
-
Thread2:gaston进入bow()方法。 并将锁定gaston对象
-
Thread1:alphonse而在bow()方法中,在gaston对象上调用bowBack()。
– > Thread1将阻塞,因为Thread2已经锁定了gaston
-
Thread2:gaston在bow()方法中,在alphonse对象上调用bowBack()。
– > Thread2将阻塞,因为Thread1已经锁定了alphonse
所以现在Thread1正在等待Thread2。 而Thread2正在等待Thread1。 这是一个僵局。
当您处理multithreading时,两个线程中的操作可以相对于彼此以任何顺序发生。 所以想象两个演员在这种情况下执行bow
,然后他们都试图执行bow_back
。 由于bow
和bow_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的弓是同步的。 所以他们都等着彼此完成。