如何理解死锁?

news2024/12/23 22:19:50

目录

今日良言:等风来,不如追风去

一、死锁

1.概念

2.死锁的三个典型情况

3.死锁的必要条件

4.如何破除死锁


🐳今日良言:等风来,不如追风去

 

🐕一、死锁

🐇1.概念

多个线程在争夺资源时,陷入了僵持状态,都无法进行下去,都在等待对方释放资源,如果不干涉,将一直僵持下去

🐇2.死锁的三个典型情况

通过这三个典型情况,可以帮助理解死锁

1).一个线程一把锁,连续加锁两次,如果锁是不可重入锁就会死锁

2).两个线程两把锁,t1和t2先分别针对锁A和锁B进行加锁,再尝试获取对方的锁.

    t1先拿到锁A,然后获取锁B,t2先拿到锁B,然后获取锁A,此时就会发生死锁.

    举个例子:有一天小马和女朋友出去吃饺子,两人都喜欢用酱油和醋蘸着饺子吃,饺子上好以

    后,小马拿起了醋,女朋友拿起了酱油,然后女朋友对小马说:你把醋给我,我用完了就给你. 然

    后,小马说:你把酱油给我,我用完了给你.如果此时两个人互不相让,此时就发生死锁.

    针对这种情况,通过下面代码来加深理解:

public class ThreadDemo21 {
    public static void main(String[] args) {
        // 创建两个实例:jiangyou和cu
        Object jiangyou = new Object();
        Object cu = new Object();
        // 创建两个线程
        Thread t1 = new Thread(() -> {
            // 先拿到cu
            synchronized (cu) {
                try {
                    // 为了让t2拿到jiangyou
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (jiangyou) {
                    System.out.println("小马拿到了醋和酱油");
                }
            }
        });
        Thread t2 = new Thread(() -> {
            // 先拿到cu
            synchronized (jiangyou) {
                try {

                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (cu) {
                    System.out.println("女朋友拿到了醋和酱油");
                }
            }
        });
        t1.start();
        t2.start();
    }
}

此时运行代码,会发现程序无任何运行结果,说明没有线程拿到两把锁.

使用jconsole观察当前线程的情况

 如果打开jconsole乜有进程的话,以管理员身份运行

3).多个线程多把锁

经典案例:哲学家就餐问题

问题描述:假设现在餐桌上有五个哲学家,每个哲学家的面前都放着一碗面条,桌子上有5根筷子,每个哲学家都需要两根筷子才可以吃面条,每个哲学家都有两种状态:1.思考人生(相当于线程的阻塞状态)   2.拿起筷子吃面条(相当于线程获取到锁,执行指令)    由于操作系统的随机调度,这5个哲学家随时都可能想吃面条或者思考人生,要想吃面条必须拿起左右手的两根筷子,情况图如下:

 

假设在某一时刻,发生极端情况,此时就会发生死锁

例如:同一时刻,所有哲学家都拿起左手的筷子,此时哲学家们都拿不到右手的筷子,都需要等待右边的哲学家将筷子放下.

🐇3.死锁的必要条件

死锁有四个必要条件:

1).互斥使用

    线程1拿到了锁,线程2就只能阻塞等待,无法使用锁.

2).不可抢占

    线程1拿到锁后,线程2不能强夺锁,只能阻塞等待,等待线程1释放锁

3).请求和保持

    线程1拿到锁A后,再尝试获取锁B,此时锁A还是保持的(并不会因为要获取锁B就释放锁A)

4).循环等待

    线程1尝试获取锁A和锁B   线程2尝试获取锁B和锁A

    线程1在获取锁B的时候等待线程2释放锁B,线程2在获取锁A的时候等待线程1释放锁A

🐇4.如何破除死锁

在死锁的四个必要条件中,前三个都是锁的基本特性,我们无法更改,所以说破除死锁的突破口就是:循环等待

如何破除循环等待呢?

最简单的办法:给锁编号,然后指定一个固定的顺序(比如从小到大)来加锁,任意线程加多把锁的时候,都让线程遵守上述顺序,此时循环等待自然破除.

以哲学家就餐问题为例:破除循环等待,为每一个筷子编号,从小到大,然后从第一个哲学家开始,规定:每次先拿编号小的筷子,然后拿编号大的筷子.

 

此时,对于哲学家5来说,无法拿起筷子,因为编号1的筷子已经被哲学家1拿走了,此时哲学家5阻塞等待,此时,对于哲学家4来说,他就可以拿起编号为5的筷子,然后吃面条,吃完后,放下筷子,此时哲学家3可以吃面条,以此类推,最后死锁就会被破除了.

针对上面的两个线程两把锁的代码,破除循环等待的代码如下.

public class ThreadDemo21 {
    public static void main(String[] args) {
        // 规定:jiangyou 是1号  cu 是2号  约定:先拿小的,再拿大的
        Object jiangyou = new Object();
        Object cu = new Object();
        // 创建两个线程
        Thread t1 = new Thread(() -> {
            // 先拿到cu
            synchronized (jiangyou) {
                try {
                    // 为了让t2拿到jiangyou
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (cu) {
                    System.out.println("小马拿到了醋和酱油");
                }
            }
        });
        Thread t2 = new Thread(() -> {
            // 先拿到cu
            synchronized (jiangyou) {
                try {

                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (cu) {
                    System.out.println("女朋友拿到了醋和酱油");
                }
            }
        });
        t1.start();
        t2.start();
    }
}

 此时运行代码:

 死锁的问题就得到了解决.

还有一种办法破除死锁的办法,银行家算法,但是过于复杂,这里只介绍简单的解决死锁的办法

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/65797.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

一种非线性权重的自适应鲸鱼优化算法IMWOA附matlab代码

✅作者简介:热爱科研的Matlab仿真开发者,修心和技术同步精进,matlab项目合作可私信。 🍎个人主页:Matlab科研工作室 🍊个人信条:格物致知。 更多Matlab仿真内容点击👇 智能优化算法 …

uni-app简介、条件编译、App端Nvue开发、HTML5+、开发环境搭建、自定义组件、配置平台环境、uniCloud云开发平台

uni-app简介 : 概述:uni-app是一个前端跨平台框架:会uni-app就可以用一套代码(类似vue语法)打包出安卓、ios、及各种小程序(微信、qq、支付宝等)端跨平台发布。 生态:完整的生态&a…

Spring6 正式发布!重磅更新,是否可以拯救 Java

简介 Spring Framework6 和 Spring Boot3 是一个跨越式的升级整个框架支持的最低 JDK 版本直接跨越到 JDK17,无论框架层还是基础设施层都做了巨大的改变,Spring 6.0 新框架具体做了哪些功能的升级与改进,是否有必要升级与使用呢?…

html网页制作期末大作业成品:基于HTML+CSS+JavaScript简洁汽车网站(7页)

🎉精彩专栏推荐 💭文末获取联系 ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 💂 作者主页: 【主页——🚀获取更多优质源码】 🎓 web前端期末大作业: 【📚毕设项目精品实战案例 (10…

「Redis」07 持久化操作(RDB、AOF)

笔记整理自【尚硅谷】Redis 6 入门到精通 超详细 教程 Redis——持久化操作(RDB、AOF) 1. RDB(Redis DataBase) 概述 RDB是什么 在指定的时间间隔内将内存中的数据集快照写入磁盘, 即 Snapshot 快照,恢…

实战 Creator 2.x 项目升级 3.x!避坑要点与基础 API 写法差异总结

最近,我将自己在 Cocos Store 上的一个 2D 项目《球球要回家》从 Creator 2.2.2 升级到 Creator 3.6.2,编程语言也从 JavaScript 全面升级至 TypeScript 并适配微信小游戏,目前在微信审核中!本篇文章就来跟大家分享一下&#xff0…

发布3天获推荐10w+,视频号内容出现新玩法?

上月,腾讯发布Q3季度财报,视频号也被重点提及,广告主对其早前上线的原生信息流广告需求强劲,像首批投放的阿玛尼等品牌的广告还曾引起过不少讨论。用户对视频号广告的关注热度高,也从侧面说明,视频号目前的…

大数据流批一体

流批一体的内涵 流批一体中的“流批”是指流处理与批处理,是两种不同的数据处理方式,而不是对数据种类的划分。具体来说,数据可以按产生的时间划分为历史数据与实时数据,亦可按数据的明细程度分为流水数据与切片数据;数…

VS2022环境下C++ DLL动态链接库的编写和调用

一、编写DLL动态链接库 1、新建动态链接库项目 2、新建类 3、宏定义 #ifdef DLL_API # define DLL_API _declspec(dllexport) # else # define DLL_API _declspec(dllimport) #endif 4、使用宏定义修饰类 /*h*/ #pragma once#ifdef DLL_API # define DLL_API _declspec(dl…

ad2019--LED灯按键类创建元件库

摘自凡亿教育 一、LED灯按键类创建元件库 1.绘制LED灯的原理图库 鼠标右击箭头所指的,然后选择倒数第三个,多边形 在画的时候可以按住,shift空格,来调整角度。 但是,一般的LED灯都是蓝色的,我们可以把它…

用MybatisPlus代码生成器生成代码

作者简介 作者名:编程界明世隐 简介:CSDN博客专家,从事软件开发多年,精通Java、JavaScript,博主也是从零开始一步步把学习成长、深知学习和积累的重要性,喜欢跟广大ADC一起打野升级,欢迎您关注&…

用帝国主义竞争算法(ICA)求解旅行商问题(TSP)(Matlab代码实现)

🍒🍒🍒欢迎关注🌈🌈🌈 📝个人主页:我爱Matlab 👍点赞➕评论➕收藏 养成习惯(一键三连)🌻🌻🌻 🍌希…

两大产品上线“粤复用”,赋能大数据智能行业发展

为深入贯彻落实国家《关于加强数字政府建设的指导意见》关于数字政府应用“一地创新、各地复用”的部署要求,促进优秀应用成果快速、可靠、低成本地复用推广,正式上线广东数字政府应用超市——“粤复用”。据悉,“粤复用”应用超市汇聚各级政…

spring-aop源码分析(2)_AnnotationAwareAspectJAutoProxyCreator后置处理器

本文将通过阅读AnnotationAwareAspectJAutoProxyCreator后置处理器的源码,分析其解析AOP通知、匹配切入点和创建AOP代理的流程。 入口 AnnotationAwareAspectJAutoProxyCreator是一个BeanPostProcessor实现,他在容器进行initializeBean的时候被调用&am…

[附源码]计算机毕业设计汽车美容店管理系统Springboot程序

项目运行 环境配置: Jdk1.8 Tomcat7.0 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术: SSM mybatis Maven Vue 等等组成,B/S模式 M…

TDH社区版上新宽表数据库Hyperbase,轻松实现海量数据的毫秒级精确检索

日前,为了降低用户接触使用大数据技术的门槛以及成本,星环科技推出TDH社区版(Transwarp Data Hub Community Edition)来帮助企业用户、高校师生、科研机构以及其他专业开发人更简单、更便捷的进行大数据分析。为了满足更多用户在存…

IT统一运维软件发展趋势浅析

在企业IT数字化转型趋势下,为支撑业务敏捷、稳定、创新发展,IT运维的重要性已日益凸显。伴随着IT运维管理目标、管理范围、管理对象及管理深度的转变,IT运维平台建设呈现管理一体化、规模扩大化、业务可视化、运维自动化、运维智能化的关键趋…

成功实施企业内容管理(ECM)的 5 个技巧

成功实施企业内容管理(ECM)的 5 个技巧 俗话说,唯一不变的就是变化。在您不懈努力发展业务的过程中,您需要改变业务流程、不断升级产品、使用技术实现自动化、让您的员工和客户满意。 改变管理方式是实施企业内容管理的一个关键考…

Vue Element UI 中 el-table 树形数据 tree-props 多层级使用避坑

实现效果: element官网提示设置tree-props为{children: ‘children’,hasChildren: ‘hasChildren’},data数据需要设置children和hasChildren属性,row-key也绑定了数据的唯一值变量id,但是树形结构的第三级就是出不来 如图 可以…

02、交换机

目录 1.、Exchange(交换机)的作用 2、Exchange(交换机)的类型 2.1.直连交换机:Direct Exchange 2.2.主题交换机:Topic Exchange 2.3.扇形交换机:Fanout Exchange 2.4.首部交换机:Headers exchange 2.5.默认交换机 2.6.Dead…