Java多线程中的死锁

Java多线程中的死锁,最简单的例子就是,线程 T1 持有对象 O1 的锁,然后去申请对象 O2 的锁;而线程 T2 持有对象 O2 的锁,然后去申请对象 O1 的锁。默认的锁申请操作都是阻塞的,这样就造成了线程互相持有对方的锁,造成死锁。复杂一些的情况可能会出现多个线程死锁的环路。
其根本原因是一个线程在持有一个锁 LOCK1 的时候,去申请另一个锁 LOCK2,即 LOCK1 没有释放,又去申请另一个锁 LOCK2,再加上锁申请是阻塞的,从而导致死锁。
简单的死锁例子:

public class Deadlock {

    private Object obj1 = new Object();
    private Object obj2 = new Object();

    public void method1() {
        try{
            synchronized (obj1) {
                Thread.sleep(2000);
                synchronized (obj2) {
                    System.out.println("method1 end");
                }
            }
        }catch(InterruptedException e){
            e.printStackTrace();
        }

    }

    public void method2() {
        try{
            synchronized (obj2) {
                Thread.sleep(2000);
                synchronized (obj1) {
                    System.out.println("method2 end");
                }
            }
        }catch(InterruptedException e){
            e.printStackTrace();
        }

    }
}

public class Thread1 extends Thread{

    private Deadlock lock;

    public Thread1(Deadlock lock){
        this.lock = lock;
    }

    @Override
    public void run() {
        lock.method1();
    }

}

public class Thread2 extends Thread{

    private Deadlock lock;

    public Thread2(Deadlock lock){
        this.lock = lock;
    }

    @Override
    public void run() {
        lock.method2();
    }

}

// 测试类
public class Test {

    public static void main(String[] args) {
        Deadlock lock = new Deadlock();
        Thread1 t1 = new Thread1(lock);
        Thread2 t2 = new Thread2(lock);
        t1.start();
        t2.start();
    }

}

可以看到对象 Deadlock 中两个方法,方法 method1 中,线程拿到 obj1 的对象锁后,申请 obj2 的对象锁;方法 method2 中,线程拿到 obj2 的对象锁后,申请 obj1 的对象锁。分别启动两个线程,执行这两个方法。
运行结果看不到结果,因为发生了死锁。可以通过 jstack 来查看:
在 cmd 中输入 jps 命令,可以显示当前所有 java 进程 pid 的命令,然后找到运行主函数的 pid,通过 jstack pid 命令,即可获得该线程的信息,在其中可以看到死锁的信息:
死锁
互相申请对方线程持有的锁,就出现了 deadlock 。
避免死锁,最好避免在同步块中调用另一个对象的同步块,但是如果不能避免,那么就需要对这几个类进行研究,看方法是否会导致死锁的闭环,如果出现要想办法调整打破死锁的闭环。通过调整代码,或者 Lock 类的 tryLock 方法设置超时时限,或者使用 ThreadLocal 等减少对象的共享等方法解决死锁。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值