什么是死锁
死锁是指多个进程因竞争资源而造成的一种僵局
(互相等待),若无外力作用,这些进程都将无法向前推进。例如,在某一个计算机系统中只有一台打印机和一台输入 设备,进程P1正占用输入设备,同时又提出使用打印机的请求,但此时打印机正被进程P2 所占用,而P2在未释放打印机之前,又提出请求使用正被P1占用着的输入设备。这样两个进程相互无休止地等待下去,均无法继续执行,此时两个进程陷入死锁状态
。
死锁产生的原因
-
系统
资源的竞争
系统资源的竞争导致系统资源不足
,以及资源分配不当
,导致死锁。 -
进程
运行推进顺序不合适
进程在运行过程中,请求和释放资源的顺序不当
,会导致死锁。
死锁的四个必要条件
互斥条件:
一个资源每次只能被一个进程使用
,即在一段时间内某资源仅为一个进程所占有
。此时若有其他进程请求该资源,则请求进程只能等待
。
占有且等待条件:
一个进程本身占有资源
(一种或多种),同时还有资源未得到满足
,正在等待其他进程释放该资源
。
不可抢占条件:
别人已经占有了某项资源,你不能因为自己也需要该资源,就去把别人的资源抢过来
。
循环等待条件:
若干进程间形成 首尾相接 循环等待资源
的关系
这四个条件是死锁的必要条件,只要系统发生死锁,这些条件必然成立,而只要上述条件之一不满足,就不会发生死锁。
避免死锁的方法
1 死锁预防
产生死锁需要四个条件,那么,只要这四个条件中至少有一个条件得不到满足
,就不可能发生死锁了。由于互斥条件
是非共享资源所必须的,不仅不能改变,还应加以保证
,所以,主要是破坏产生死锁的其他三个条件。
1 破坏“占有且等待条件”
:
方法1
:所有的进程在开始运行之前,必须一次性地申请其在整个运行过程中所需要的全部资源
。
- 优点:
简单易实施且安全
。 - 缺点:因为某项资源不满足,进程无法启动,
而其他已经满足了的资源也不会得到利用
,严重降低了资源的利用率
,造成资源浪费。使进程经常发生饥饿现象
。
方法2
:该方法是对第一种方法的改进,允许进程只获得运行初期需要的资源
,便开始运行
,在运行过程中逐步释放掉分配到的已经使用完毕的资源
,然后再去请求新的资源
。这样的话,资源的利用率会得到提高
,也会减少进程的饥饿问题
。
2 破坏“不可抢占条件”
:当一个已经持有了一些资源的进程,在提出新的资源请求没有得到满足时
,它必须释放已经保持的所有资源
,待以后需要使用的时候再重新申请
。这就意味着进程已占有的资源会被短暂地释放或者说是被抢占了
。
该种方法实现起来比较复杂
,且代价也比较大
。释放已经保持的资源很有可能会导致进程之前的工作失效等
,反复的申请和释放资源
会导致进程的执行被无限的推迟
,这不仅会延长进程的周转周期
,还会影响系统的吞吐量
。
3 破坏“循环等待条件”
:采用资源有序分配
,其基本思想是将系统中的所有资源顺序编号
,将紧缺的,稀少的采用较大的编号
,在申请资源时必须按照编号的顺序进行
,一个进程只有获得较小编号的资源才能申请较大编号的资源
。
这样虽然避免了循环等待
,但是这种方法是比较低效的
,资源的执行速度会变慢
,并且可能在没有必要的情况下拒绝资源的访问,比如说,进程c想要申请资源1,如果资源1并没有被其他进程占有,此时将它分配个进程c是没有问题的,但是为了避免产生循环等待,该申请会被拒绝,这样就降低了资源的利用率。
2、避免死锁
在使用前进行判断
,只允许不会产生死锁的进程申请资源
。死锁的避免是利用额外的检验信息
,在分配资源时判断是否会出现死锁,只在不会出现死锁的情况下才分配资源。
两种避免办法:
1、如果一个进程的请求
会导致死锁,则不启动该进程
2、如果一个进程的增加资源请求
会导致死锁 ,则拒绝该申请
。
避免死锁的具体实现通常利用银行家算法
a、银行家算法的相关数据结构
可利用资源向量Available
:用于表示系统里边各种资源剩余的数目。由于系统里边拥有的资源通常都是有很多种(假设有m种),所以,我们用一个有m个元素的数组来表示各种资源。数组元素的初始值为系统里边所配置的该类全部可用资源的数目,其数值随着该类资源的分配与回收动态地改变。
最大需求矩阵Max
:用于表示各个进程对各种资源的额最大需求量。进程可能会有很多个(假设为n个),那么,我们就可以用一个nxm的矩阵来表示各个进程多各种资源的最大需求量
分配矩阵Allocation
:顾名思义,就是用于表示已经分配给各个进程的各种资源的数目
。也是一个nxm的矩阵。
需求矩阵Need
:用于表示进程仍然需要的资源数目
,用一个nxm的矩阵表示。系统可能没法一下就满足了某个进程的最大需求(通常进程对资源的最大需求也是只它在整个运行周期中需要的资源数目,并不是每一个时刻都需要这么多),于是,为了进程的执行能够向前推进,通常,系统会先分配个进程一部分资源保证进程能够执行起来。那么,进程的最大需求减去已经分配给进程的数目,就得到了进程仍然需要的资源数目了。
银行家算法通过对进程需求、占有和系统拥有资源的实时统计
,确保系统在分配给进程资源不会造成死锁才会给与分配
。
死锁避免的优点
:不需要死锁预防
中的抢占
和重新运行
进程,并且比死锁预防的限制要少
。
死锁避免的缺点
:
- 必须
事先声明每个进程请求的最大资源量
- 考虑的进程必须无关的,也就是说,
它们执行的顺序必须没有任何同步要求的限制
分配的资源数目必须是固定
的。
在占有资源时,进程不能退出
3 死锁检测与解除
在检测到运行系统进入死锁,进行恢复。
允许系统进入到死锁状态
死锁检测
下图截自《操作系统–精髓与设计原理》
死锁的解除
如果利用死锁检测算法检测出系统已经出现了死锁 ,那么,此时就需要对系统采取相应的措施。常用的解除死锁的方法
:
1、抢占资源
:从一个或多个进程中抢占足够数量的资源分配给死锁进程
,以解除死锁状态
。
2、终止(或撤销)进程
:终止或撤销系统中的一个或多个死锁进程
,直至打破死锁状态
。
a、终止所有的死锁进程
。这种方式简单粗暴,但是代价很大,很有可能会导致一些已经运行了很久的进程前功尽弃
。
b、逐个终止进程
,直至死锁状态解除。该方法的代价也很大,因为每终止一个进程就需要使用死锁检测来检测系统当前是否处于死锁状态
。另外,每次终止进程的时候终止那个进程呢?每次都应该采用最优策略来选择一个“代价最小”的进程来解除死锁状态
。一般根据如下几个方面来决定终止哪个进程
:
- 进程的
优先级
- 进程
已运行时间以及运行完成还需要的时间
- 进程
已占用系统资源
- 进程
运行完成还需要的资源
终止进程数目
- 进程
是交互还是批处理