锁在使用时产生的问题——死锁问题

        观察死锁是如何产生的,观察下面这段代码

public static void main(String[] args) {
        Object lock1 = new Object();
        Object lock2 = new Object();
        Thread t1 = new Thread(() ->{
            //获取lock1
            synchronized (lock1){
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                //持有lock1的前提下获取lock2
                synchronized (lock2){
                    System.out.println("t1有两把锁");
                }
            }
        });
        Thread t2 = new Thread(() ->{
            //获取lock2
            synchronized (lock2){
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                //持有lock2的前提下获取lock1
                synchronized (lock1){
                    System.out.println("t2有两把锁");
                }
            }
        });
        t1.start();
        t2.start();
    }

        运行一段时间后,许久都没有等到t1或者t2打印的内容,并且通过工具可以观察到,此时t1和t2都处于BLOCKED状态

        并且t1的锁持有者为t2,t2的锁持有者为t1,因为这时候t1在等待t2释放lock2,t2在等待t1释放lock1,这时就产生了死锁.

        死锁产生的原因(必要条件)

        1.互斥使用,获取锁的过程是互斥的。

        一个线程拿到这把锁,另一个线程也想拿到这把锁,就要等待

        2.不可抢占

        一个线程拿到锁之后,其他的线程只能等待该线程主动释放锁,不能直接抢过来

        3.请求保持

        一个线程拿到锁A后,在持有锁A的前提下去尝试获取锁B

        4.环路等待

        如A在等待B释放锁2,B在等待C释放锁3,而C在等待A释放锁1,这时等待就形成了一个循环,产生了死锁

        如何解决死锁?

        想要解决死锁,就要尝试破坏产生死锁的必要条件

        对于条件1和条件2,这都是锁的特性。如果把这两个条件破坏掉,那么这个“锁”也不能叫锁了,所以这两个条件无法破坏。观察条件3,这个问题似乎是由代码结构产生的,而一些情况下,如 用户的需求就是这样 那么我们去破坏条件3的优先级也没有那么高。

        那只剩条件4了,关于这个条件的解决有很多优秀的案例 如 银行家算法 以及 哲学家吃面问题,这里不再展开赘述。破坏这个条件只需要我们规划加锁顺序,对加锁顺序进行优化后,虽然可能导致执行效率不如预期,但是可以避免死锁问题。

        

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值