概述
在计算机系统中有许多互斥的资源,若两个进程同时使用则会出现不可预知的问题。所谓 **死锁(Dead lock) **即两个以上的进程都要使用对方已经占有的资源导致无法继续运行的现象,造成死锁的可能有很多种。
在了解死锁前要对信号量及互斥有一定了解,如果不了解可以先查看此文:操作系统 进程
下面简单看几个例子:
-
因执行顺序不当造成的死锁
有两个进程 P 1 , P 2 P_1, P_2 P1,P2,它们共享资源 A , B A, B A,B,假设两个进程并发执行,按照下图顺序请求和释放资源:
当 P 1 P_1 P1请求资源
A
, P 2 P_2 P2请求资源B
时,它们的请求都可以被满足;随后当 P 1 P_1 P1请求资源B
, P 2 P_2 P2请求资源A
时,它们的请求都无法被满足,因为两个进程需要的资源都被对方占用,两个进程都无法继续执行,因而造成死锁。 -
因资源分配不当造成的死锁
系统中有 m m m个资源被 n n n个进程共享,当每个进程要求 k k k个资源,且 m < n k m<nk m<nk(即资源数小于进程所要求的总数)。这种情况若系统采用轮流为每个进程分配资源的策略则可能造成死锁,如每轮为进程分配一个资源,第二轮再分配一个,直到出现一轮可能无法完成分配则造成所有进程的死锁。
-
因PV操作不当造成的死锁
若进程一文中提到过的消费者生产者问题的两个进程改为如下:
上述流程会在信号量
S1=S2=0
时造成死锁。 P 2 P_2 P2从缓冲区取产品前,先执行了P(S2)
,由于S2=-1
,故 P 2 P_2 P2等待;而 P 1 P_1 P1将产品送入缓冲区后,执行P(S1)
,由于S1=-1
, P 1 P_1 P1也只能等待。这样一来两个进程都无法继续执行。
死锁产生的原因及4个必要条件
从上述的例子就能看出,死锁主要出现在资源竞争及进程推进顺序错误。
其4个必要条件就是:
- 互斥
- 请求保持
- 不可剥夺
- 环路
所谓环路是 进程资源有向图 中产生的环路,这个图比较简单,由方框、圆圈、有向边组成。用方框表示资源、圆圈表示进程。请求资源的表示方法:○→□;分配资源的表示方法:□→○;若不太理解可搜索关键字,过于简单就不阐述了。
死锁的处理
主要有4种处理策略:鸵鸟策略(即不处理)、预防策略、避免策略、检测与解除死锁策略。下面一一简单介绍一下。
死锁预防
死锁预防是采用某种策略限制并发进程对资源的请求,破坏死锁产生的4个必要条件之一。
使系统在任何时刻都无法满足产生死锁的必要条件。其有两种方法:
-
预先静态分配法
破坏不可剥夺条件,使资源总是预先分配,保证资源无需等待。但该方法的缺点在于降低了资源的利用率,也降低了程序的并发程度。并且需要使用的资源不总是可以预先知道的。
-
资源有序分配法
破坏环路条件,把资源分类按顺序排列,保证不形成环路。该方法存在的问题是限制进程对资源的请求,且资源的排序也占用系统开销。
死锁避免
如果说死锁预防是破坏4个必要条件之一,严格防止死锁的产生。那么避免就是不那么严格限制产生死锁的条件。最著名的死锁避免算法就是Dijkstra提出的银行家算法。
银行家算法对于进程发出的每一个系统可以满足的资源请求加以检测,若分配资源后会使系统进入不安全状态,则不予分配;若分配资源后系统处于安全状态,则实施分配。与死锁预防策略相比,一定程度提高了资源的利用率。
关键在于如何判断系统是否出于安全,所谓的安全状态,指的其实是系统能按照某种顺序来为进程分配所需资源,直至最大需求,且每个进程都可顺利完成。通常将这个顺序序列称为安全序列,若系统不存在这样的安全序列,则称系统处于不安全状态。
死锁检测与解除
这种方式和前两种不同,它不回避死锁的产生,不对资源分配加以限制。但系统通过定时的检测是否存在死锁,若有则设法加以解除。
通常,解除采用如下方式:
- 资源剥夺法——从一些进程中强行收回足够数量的资源给死锁进程。
- 撤销进程法——根据特定策略,逐个撤销死锁的进程,直至死锁不再持续。