当前位置: 首页 > article >正文

死锁的成因与解决方案

目录

死锁的概念与成因

栗子

死锁的情况

哲学家问题

如何避免死锁

必要条件

死锁的解决方案

总结


死锁的概念与成因

        多个线程同时被阻塞,他们中的其中一个或者全部都在等待某个资源的释放,导致线程无限期被阻塞,程序无法停止

栗子

        我和美女a出去吃饺子,吃饺子要醋和酱油

        我拿起醋他拿起了酱油

        我说: 把酱油给我我给你醋

        他说: 他醋给我我给你酱油

        结果两人争执不下谁也不让谁,就构成死锁,我两就是两个线程

死锁的情况

一线程一把锁

        可重入锁不会产生死锁,不可重入锁会发生(之前的文章有介绍过可重入锁)

两个线程两把锁

        是可重入锁也会发生死锁

N个线程,M把锁

        就更加容易发生死锁了

哲学家问题

        这就牵扯到哲学家就餐问题

如图 

        这五个哲学家,只会进行思考人生和吃饭

        思考人生放下筷子,吃饭就会拿起筷子,只有拿起两双筷子吃完才会放下

        如果只拿起一只,就会一直拿着不会放开

        假设五个哲学家每个人都拿起自己左手边的筷子,那就会永远发生阻塞,产生死锁

如何避免死锁

        先了解死锁的四个必要条件

必要条件

        1. 互斥使用. 一个线程拿到锁后,另一个线程无法使用

        2. 不可抢占. 一个线程拿到锁以后,只能自己主动释放,不能被其他线程抢占

        3. 请求与保持. 在资源请求者请求到其他资源的时候,同时保持对原有资源的抢占(吃着碗里的,看着锅里的)

        4. 循环等待. 存在一个等待队列 : p1 占用 p2 的资源, p2 占用着 p1 的资源,就形成了一个等待环路

如果上述条件都成立,那就会形成死锁.

但是如果打破其中一条就会使死锁消失

其中最容易破坏的就是循环等待

死锁的解决方案

        假设有 n 个线程想获取 m 把锁,我们规定一个所排序,比如(1,2,3,4.........)按照从小到大来进行获取锁,这样可以破坏环路,防止循环等待(可能很难理解,看一段代码就容易理解了)

        先看一段代码

    public static Object locker1 = new Object();
    public static Object locker2 = new Object();
    
    public static void main(String[] args) {
        Thread t1 = new Thread(() -> {
            synchronized(locker1){
                synchronized (locker2){
                    //工作
                }
            }
        });
        t1.start();
        Thread t2 = new Thread(() -> {
            synchronized(locker2){
                synchronized (locker1){
                    //工作
                }
            }
        });
        t2.start();
    }

        在这段代码中就会出现循环等待的情况

    public static Object locker1 = new Object();
    public static Object locker2 = new Object();
    
    public static void main(String[] args) {
        Thread t1 = new Thread(() -> {
            synchronized(locker1){
                synchronized (locker2){
                    //工作
                }
            }
        });
        t1.start();
        Thread t2 = new Thread(() -> {
            synchronized(locker1){
                synchronized (locker2){
                    //工作
                }
            }
        });
        t2.start();
    }

        只需要固定加锁的顺序,先获取到 1 才可以获取 2 ,这样就会破坏循环等待的情况

总结

        1. 死锁形成的四个条件

        2. 破坏循环等待是最常用的方法


http://www.kler.cn/news/330136.html

相关文章:

  • 景联文科技入选《2024中国AI大模型产业图谱2.0版》数据集代表厂商
  • Vue3.0面试题汇总
  • 如何实现一个Mini Spring Boot
  • Leecode热题100-283.移动零
  • AI学习指南深度学习篇-权重正则化的实现机制
  • 技术成神之路:设计模式(十八)适配器模式
  • 深度学习中的优化方法(Momentum,AdaGrad,RMSProp,Adam)详解及调用
  • 后台管理系统脚手架
  • ICM20948 DMP代码详解(58)
  • 深入探索 Pygwalker:Python 数据可视化的强大工具
  • STM32-MPU6050+DAM库源码(江协笔记)
  • Ps:打开与置入
  • C++——函数功能是:将两个两位数的正整数a、b合并成一个整数c,合并规则是将a的十位和个位分别放在c的千位和个位,将b的十位和个位分别放在c的十位和百位。
  • 小论树形dp
  • 游戏如何对抗改包
  • 【JavaScript】JIT
  • 【gradio】gradio构建webui demo时只支持一个访问?
  • [BCSP-X2024.小高3] 学习计划
  • 网络编程套接字TCP
  • DNS与ICMP
  • 毕业设计选题:基于ssm+vue+uniapp的校园水电费管理小程序
  • 查找与排序-归并排序
  • rabbitMq-----broker服务器
  • 解决nginx+tomcat宕机完美解决方案
  • 【数据结构】堆(Heap)详解----定义堆、初始化,删除、插入、销毁、判空、取堆顶
  • 试用Foxit PDF: 在网页中单页展示PDF
  • 计算机网络期末复习真题(附真题答案)
  • 构建.NET Core Web API为Windows服务安装包
  • 配置Scrapy项目
  • 3、AI测试辅助-测试计划编写(自动生成任务甘特图)