两个线程互相等待对方释放同步监视器就会发生死锁
public class A { public synchronized void foo(B b) { System.out.println("当前线程:" + Thread.currentThread().getName() + "进入A实例的foo方法"); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("当前线程:" + Thread.currentThread().getName() + "企图调用B实例的last方法"); b.last(); } public synchronized void last() { System.out.println("进入到A的last方法"); } }
public class B { public synchronized void bar(A a) { System.out.println("当前线程:" + Thread.currentThread().getName() + "进入B的bar方法"); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("当前线程:" + Thread.currentThread().getName() + "企图调用A实例的last方法"); a.last(); } public synchronized void last(){ System.out.println("进入B的last方法内"); } }
public class DeadLock implements Runnable{ A a = new A(); B b = new B(); public void init() { Thread.currentThread().setName("主线程"); a.foo(b); System.out.println("进入主线程之后"); } @Override public void run() { Thread.currentThread().setName("副线程"); b.bar(a); System.out.println("进入副线程之后"); } public static void main(String[] args) { DeadLock dl = new DeadLock(); new Thread(dl).start(); dl.init(); } }
结果分析:
副线程先执行 —— b调用bar() —— 进入bar方法前“副线程”对B对象加锁 —— 执行sleep,睡2s —— cpu切换执行到另一个线程
主线程开始执行 —— a调用foo() —— 进入foo方法前“主线程”对A对象加锁 —— 执行sleep,睡2s —— cpu切换执行到另一个线程(此时副线程醒了)
副线程醒了继续向下执行 —— 企图调用A实例的last同步方法 —— 但是此时主线程保持着对A对象的加锁,那么副线程就等待主线程对A的释放,等待......
主线程2s过后也醒了 ,继续向下执行 —— 企图调用B实例的last同步方法 —— 但是副线程仍然保持着对B对象的加锁,主线程等待副线程对B的释放,等待......
相互等待 , 就耗着了 , 死锁。
注意: Thread的suspend() 方法很容易导致死锁 , java不推荐使用该方法来暂停线程。