死锁以及如何避免死锁


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

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

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

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

程序员:…

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

死锁

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

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

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

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

相关推荐

  1. 以及如何避免

    2024-04-11 15:04:06       39 阅读
  2. 资源、如何监测

    2024-04-11 15:04:06       41 阅读
  3. 问题,4个必要条件+避免

    2024-04-11 15:04:06       65 阅读
  4. 2024-04-11 15:04:06       45 阅读
  5. 的定义以及产生的必要条件,处理

    2024-04-11 15:04:06       45 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-04-11 15:04:06       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-04-11 15:04:06       100 阅读
  3. 在Django里面运行非项目文件

    2024-04-11 15:04:06       82 阅读
  4. Python语言-面向对象

    2024-04-11 15:04:06       91 阅读

热门阅读

  1. 如何理解JVM

    2024-04-11 15:04:06       32 阅读
  2. Spring之事务底层源码解析

    2024-04-11 15:04:06       32 阅读
  3. CSS 选择器 – 类、名称、子选择器

    2024-04-11 15:04:06       30 阅读
  4. 为什么俗套的电邮“钓鱼”攻击,频频得手

    2024-04-11 15:04:06       35 阅读
  5. 【c/c++】fprintf和fwrite使用及作用介绍

    2024-04-11 15:04:06       34 阅读
  6. Part1_带复位的8通道I2C开关PCA9548A使用方法介绍

    2024-04-11 15:04:06       38 阅读
  7. 关于c++的命名空间

    2024-04-11 15:04:06       33 阅读
  8. 水土流失监测设备解析

    2024-04-11 15:04:06       34 阅读
  9. 设计模式(013)行为型之观察者模式

    2024-04-11 15:04:06       33 阅读
  10. HTML中meta标签的作用

    2024-04-11 15:04:06       33 阅读