java 多线程 7 : 死锁

两个线程互相等待对方释放同步监视器就会发生死锁

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不推荐使用该方法来暂停线程。

温故而知新
原文地址:https://www.cnblogs.com/Uzai/p/9679001.html