死锁的产生条件以及如何避免死锁
文章目录
- 前言
- 一、哲学家就餐问题
- 二、造成死锁的条件
- 三、如何避免死锁
- 总结
前言
死锁是并发编程中非常重要的一个知识点,死锁使程序运行无法得到正确的结果同时降低操作系统的资源利用率,危害非常大。本篇文章以哲学家就餐问题作为引导,讲解产生死锁的条件以及如何避免死锁,供参考学习。
一、哲学家就餐问题
五位哲学家围坐在一张圆形餐桌旁,做以下两件事情之一:吃饭或者思考。
1.哲学家围在⼀起先思考,思考中途饿了就会想吃饭。
2.每两个哲学家之间有一只餐叉。哲学家必须用两只餐叉吃东西,并且他们只能使用自己左右手边的那两只餐叉,吃完的时候会把叉子放回原处,继续思考。
哲学家从来不交谈,这就很危险,可能产生死锁,如每个哲学家都拿着左手的餐叉,永远都在等右边的餐叉(或者相反),这样他们几个就搁这卡bug了。
二、造成死锁的条件
我们为了防止多线程竞争共享资源而导致数据错乱,都会在操作共享资源之前加上锁,只有成功获得到锁的线程,才能操作共享资源,获取不到锁的线程就只能等待,直到锁被释放。
在哲学家就餐问题中,涉及到了多个线程(哲学家)竞争共享资源(叉子),如果不加以控制可能就会出现死锁的情况。
造成死锁的四个条件:
- ⼀个资源每次只能被⼀个线程使用(一个叉子只能被一个哲学家使用)
- ⼀个线程在阻塞等待某个资源时,不释放已占有资源 (即使拿不到第二个叉子,哲学家也不会放弃已经拿到的叉子)
- ⼀个线程已经获得的资源,在未使用完之前,不能被强姓剥夺 (不能从其他哲学家手上抢走叉子)
- 若干线程形成头尾相接的循环等待资源关系(每个哲学家都在等待下一个人释放叉子,形成了一个环)
这是造成死锁必须要达到的4个条件!如果要避免死锁,只需要不满⾜其中某⼀个条件即可。但是其中前3个条件是作为锁要符合的条件,所以要避免死锁就需要打破第4个条件,不出现循环等待锁的关系。
下面就来用一段代码演示一下死锁的产生情况:
public class DieSynchronizedThread extends Thread{static Object A=new Object();static Object B=new Object();boolean flag;@Overridepublic void run() {if(flag){synchronized (A){System.out.println(Thread.currentThread().getName()+"拿到了A");synchronized (B){System.out.println(Thread.currentThread().getName()+"拿到了B");}}}else{synchronized (B){System.out.println(Thread.currentThread().getName()+"拿到了B");synchronized (A){System.out.println(Thread.currentThread().getName()+"拿到了A");}}}}public static void main(String[] args) {DieSynchronizedThread t1=new DieSynchronizedThread();DieSynchronizedThread t2=new DieSynchronizedThread();t1.setName("小黑");t2.setName("小白");t1.flag=true;t2.flag=false;t1.start();t2.start();}
}
小白和小黑都需要拿到A和B才能完成自己的操作,但由于没有对获取资源进行控制,小黑先去拿了A,小白先去拿了B,导致它们两个卡了bug,出现了死锁。
三、如何避免死锁
上文说了要打破死锁,就需要打破第4个条件,即不出现循环等待锁的关系。打破这个条件最常用的方法就是资源有序分配法,即两个或多个线程以相同的顺序去申请自己需要的资源。下面将上面的代码修改一下,两个线程都先去获取A,再去获取B。
if(flag){synchronized (A){System.out.println(Thread.currentThread().getName()+"拿到了A");synchronized (B){System.out.println(Thread.currentThread().getName()+"拿到了B");}}}else{synchronized (A){System.out.println(Thread.currentThread().getName()+"拿到了A");synchronized (B){System.out.println(Thread.currentThread().getName()+"拿到了B");}}}
这样它们之间就可以进行愉快的玩耍了,因为只有获取了A才能去获取B,不会出现拿到A,B被别人抢了的情况。
作为程序员,在开发过程中:
- 要注意加锁顺序,保证每个线程按同样的顺序进⾏加锁
- 要注意加锁时限,可以针对所设置⼀个超时时间
- 要注意死锁检查,这是⼀种预防机制,确保在第⼀时间发现死锁并进⾏解决
总结
简单来说,死锁问题的产生是由两个或者以上线程并行执行的时候,争夺资源而互相等待造成的。死锁有四个条件,缺一不可,而打破死锁需要打破第四个条件,最常用的方法就是资源有序分配法。
死锁的产生条件以及如何避免死锁相关推荐
- 死锁发生的条件以及如何避免死锁
ⅰ死锁 ¤死锁,它是操作系统或软件运行的一种状态:在多任务下,当一个或多个进程等待系统资源而资源又被系统本身或其它进程占用时,就形成了死锁. 死锁发生的最常见形式是两个或多个线程等待被另一个线程占用的 ...
- 死锁是什么?死锁产生的条件?如何避免死锁?以及死锁的示例代码(Java代码)
文章目录 一.什么是死锁? 二.产生死锁的条件? 三.产生死锁的示例代码(java) 四.如何避免死锁? 一.什么是死锁? 下面图片参考 JavaGuide中的内容: 死锁的概念: 死锁:指的是相互两 ...
- 什么是死锁?死锁产生的条件?
什么是死锁?死锁产生的条件? 什么是死锁: 在两个或者多个并发进程中,如果每个进程持有某种资源而又等待其它进程释放它或它们现在保持着的资源,在未改变这种状态之前都不能向前推进,称这一组进程产生了死锁. ...
- 死锁产生的条件+排除死锁的方法
问:请问进程调度中产生死锁的必要条件是什么?解决死锁有几种办法 答: 产生死锁的四个必要条件: (1)互斥条件:一个资源每次只能被一个进程使用. (2)请求与保持条件:一个进程因请求资源而阻塞时,对已 ...
- 哲学家就餐与死锁问题,死锁产生的条件以及解决方案
请结合经典案例-哲学家就餐,来谈谈你对死锁的理解,以及怎么预防和解除死锁? 哲学家就餐 描述:在一张圆桌上,有n个哲学家,n支筷子,他们的生活方式只是交替地进行思考和进餐,饥饿时便试图取其左.右最靠近 ...
- 死锁产生的原因及条件、如何避免死锁
一.死锁的定义 是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造.成的一种阻塞的现象,若无外力作用,它们都将无法推进下去.此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等 ...
- 死锁发生的条件和预防
所谓死锁:是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去.此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程. ...
- 「操作系统」深入理解死锁(什么是死锁?死锁形成条件?如何避免死锁?如何排查死锁?)
「操作系统」深入理解死锁(什么是死锁?死锁形成条件?如何避免死锁?如何排查死锁?) 参考&鸣谢 什么是线程死锁?形成条件是什么?如何避免? Java圈子 面试官:如何快速排查死锁?如何避免死锁 ...
- 操作系统常问面试问题 3 —— 死锁(deadlock)(产生的条件、死锁避免(银行家算法)、死锁检测)
死锁(产生的条件.死锁避免(银行家算法).死锁检测) 死锁(deadlock) 1.定义 2.产生的条件 3.死锁避免 3.1.银行家算法 3.1.1.实现过程 4.死锁检测 5.死锁恢复 6.鸵鸟算 ...
最新文章
- 【内网穿透】生壳SSH映射 for Linux 使用教程
- Memcache 内存分配策略和性能(使用)状态检查
- vmware虚拟的ubuntu18.04死机,尝试关闭时关机报“虚拟机xxx繁忙”
- Python RSA
- maven 执行testng.xml文件失败解决问题
- QCC300x 芯片ota升级PSKey 操作方法
- 二年级课程表(4月2日-4月8日)
- Python批量自定义文件夹图标
- java中的example_GitHub - lilei644/spring-java-example: 记录开发以及学习过程中Spring、Java相关的示例...
- 手机通过adb工具安装应用
- 线性回归和逻辑回归的典型面试考点
- 【视频】海康威视摄像头RTSP协议格式
- django设置为中文语言
- OpenLayers中文文档2栅格重投影
- 白菜个人导航页2.0
- 每个前端都需要知道这些面向未来的CSS技术
- NPOI创建excel表头
- 怎么自定义ZBrush 4R7中按钮颜色
- 生活中有什么值得坚持的好习惯?
- 如何图片转PDF?PDF编辑器也能轻松实现
热门文章
- 抖音素材哪里收集_抖音短视频的内容素材在哪里找?抖音内容素材在哪里收集?...
- 卷积神经网络卷积计算具体过程?
- 计算机一级photoshop试题,计算机一级photoshop选择题练习及答案
- C++中std::allocator的使用
- php匹配邮箱,php email邮箱正则
- js 数组遍历符合条件跳出循环体_JavaScript跳出forEach循环
- Android 震动功能
- Unity中的Character Controller组件的基本使用
- Python 全栈系列122 redis消息队列搭建
- 使用Darknet训练您自己的数据集(YOLOV 3)