死锁以及如何避免死锁


有一个笑话,在疫情期间,某地的健康码突然崩溃,无法打开,于是维护健康码的程序员火速赶去公司想维护健康码,但是到了公司楼下,被保安大爷拦下

大爷:得看见正常的健康码才能进去

程序员:我得进去将健康码修复了才能给你看

大爷:那不行,得看见健康码才能让你进去

程序员:…

这明显是出现了矛盾,而这样的互不相让的情况在计算机线程中就是死锁

死锁

在多线程编程中,我们为了防止多线程竞争共享资源而导致数据错乱,都会在操作共享资源之前加上互斥锁,只有成功获得到锁的线程,才能操作共享资源,获取不到锁的线程就只能等待,直到锁被释放。

那么,当两个线程为了保护两个不同的共享资源而使用了两个互斥锁,那么这两个互斥锁应用不当的时候,可能会造成两个线程都在等待对方释放锁,在没有外力的作用下,这些线程会一直相互等待,就没办法继续运行,这种情况就是发生了死锁。(可以借用上面的例子来理解)

死锁只有同时满足下列四个条件才能触发

  • 互斥:资源处在非共享模式,一次只能一个线程使用,直到释放后,其他线程才能使用
  • 持有并等待:一个线程至少持有一个资源,并等待另一个资源,此资源被其他线程占用
  • 不可剥夺:资源无法被抢占,只有当释放后,资源才能被其他线程使用
  • 循环等待:在一组线程中[p0,p1,p2],p0等待p1释放资源,p1等待p2释放资源,p2等待p0释放资源。

死锁样例代码

public static void main(String[] args) {
        Object clocker1=new Object();
        Object clocker2=new Object();

        Thread t1=new Thread(()->{
            synchronized (clocker1){
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }

                System.out.println("t1 等待");
                synchronized (clocker2){
                    System.out.println("t1 拿到clocker2资源 ");
                }
            }
        });

        Thread t2=new Thread(()->{
            synchronized (clocker2){
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }

                System.out.println("t2 等待");
                synchronized (clocker1){
                    System.out.println("t2 拿到clocker1资源 ");
                }
            }
        });
        t1.start();
        t2.start();
    }

避免死锁的方法

解决死锁的方法可以从多个角度去分析,一般的情况下,有预防,避免,检测和解除四种

  • 预防 是采用某种策略,限制并发进程对资源的请求,从而使得死锁的必要条件在系统执行的任何时间上都不满足。
  • 避免则是系统在分配资源时,根据资源的使用情况提前做出预测,从而避免死锁的发生
  • 检测是指系统设有专门的机构,当死锁发生时,该机构能够检测死锁的发生,并精确地确定与死锁有关的进程和资源。
  • 解除 是与检测相配套的一种措施,用于将进程从死锁状态下解脱出来

这里博主水平有限,只能给出一篇javaguide的相关博客,大家可以自行查看:操作系统常见面试题总结(上) | JavaGuide

  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值