文章目录
一、死锁概述
1. 死锁的定义
- 如果一组进程中的每一个进程 都在等待 仅由该组进程中的其他进程 才能引发的事件,那么该组进程是死锁的。
2. 产生死锁的必要条件
- 产生死锁必须同时具备下面四个必要条件,只有其中一个条件不成立,死锁就不会发生。
- 互斥条件。进程对所分配的资源进行排他性使用。即该资源只允许一个进程使用,其他进程如果请求该资源只能等待。
- 请求和保持条件。进程已经保持一至少一个资源,但又提出了新的资源请求,而新资源已被其他进程占有,导致进程被阻塞。
- 不可抢占条件。 进程已获得的资源在未使用完之前不能被抢占,只有进程在使用完之后才能释放。
- 循环等待条件。发生死锁时,必然存在一个进程资源循环链,即进程集合 [p0, p1, p2, …, pn] 中 p0等待 p1 的资源,p1 等待 p2 的资源, pn-1 等待 pn 的资源…pn 等待 p0 的资源。
3. 死锁的处理
死锁的处理可以分为下面这四种:
- 预防死锁。该方法是通过产生死锁的四个必要条件中的一个或者几个来预防产生死锁。
- 避免死锁。该方法是在资源的动态分配的过程中,用某种方法预防系统进入不安全状态,从而可以避免发生死锁。
- 检测死锁。该方法允许进程发生死锁,但可以检测死锁的发生,然后通过适当的措施将进程解脱出来。
- 解除死锁。当已经检测出死锁时,就采用相应的措施,将进程解脱出来,常用的方法是撤销一些进程,回收他们的资源。将他们分配给处于阻塞状态的进程。
二、预防死锁
1. 破坏“请求和保持”条件
为了破坏“请求和保持”条件,可以通过以下两个不同的协议实现:
- 第一种协议
- 该协议规定,所有进程在开始运行之前,必须一次性的申请其整个运行过的所需要的全部资源。此时若系统有足够的资源分配某进程,则破坏了“请求”条件。如果系统资源不足,则破坏了“保持”条件。
- 第一种协议简单,易行且安全,但缺点也比较明显:
- 资源被严重浪费,严重恶化了资源的利用率
- 使进程经常发生饥饿现象。
- 第二种协议
- 该协议是对第一种协议的改进,它允许一个进程只获得运行初期所需的资源后,便开始运行。进程运行过程中再逐步释放已分配给自己的、且已经用完的全部资源,再去请求新的资源。
- 第二种协议相比于第一种协议而言,提高设备的利用率,也减少了进程发生饥饿的几率。
2. 破坏“不可抢占”条件
- 为了能破坏“不可抢占”条件,协议中规定,当一个已经保持了某些不可被抢占资源的进程,提出新的资源请求而不能得到满足,它必须释放已经保持的所有资源,待以后需要时再重新申请。
- 这意味着进程已占用的资源会暂时释放,从而破坏了“不可抢占的”条件。
- 缺点:这种方法实现复杂,且代价较大。还可能因为反复申请和释放资源导致进程的执行被无限推迟。这不仅延长了进程的周转时间,而且也增加了系统的开销,降低了系统的吞吐量。
3. 破坏"循环等待”条件
- 一个能保证“循环等待”条件不成立的方法是:对系统所有资源类型进行线性排序,并赋予不同的序号。
- 排序后,便可以采用这样的预防协议:规定每个进程必须按照序号递增的顺序请求资源。如果需要多个同类资源单元,则必须一起请求。
- 假如某进程请求到高序号资源后,又想请求低序号资源,就必须先释放高序号资源再申请低序号资源。这样的资源分配图中不会出现环路,因此破坏了“循环等待”条件。
- 优点:资源利用率和系统吞吐量都有比较明显的改善。
- 缺点:
- 系统中各类资源所规定的序号必须稳定,这就限制了新类型设备的增加;
- 可能会发生作业使用各类资源的顺序与系统规定的顺序不同,造成资源的浪费;
- 这种按照规定次序申请资源的方法会限制用户简单、自主的编程。
三、避免死锁
- 在避免死锁方法中,把系统的状态分为安全状态和不安全状态。安全状态中,可避免死锁状态;不安全状态中,进程可能进入死锁状态。
- 避免死锁方法的基本思想就是,让系统始终处于安全状态。
- 最具有代表性避免死锁的算法就是Dijkstra的银行家算法。
1. 银行家算法概述
基本思想:
- 在每个新进程进入系统时,他必须声明在运行过程中,可能需要的每种资源类型的最大单元数目(数目不超过系统拥有的资源总量)。
- 当进程请求一组资源时,系统必须首先在确定是否有足够的资源分配给该进程。
- 若有,在进一步计算将这些资源分配给进程后,是否会使系统处于不安全状态。如果处于安全状态,才将资源分配给他;否则,让进程等待。
2. 银行家算法中的数据结构
为实现银行家算法,在系统中必须要有这样四个数据结构,分别用来描述系统中可利用的资源,所有进程对资源的最大需求,系统中的资源分配,以及所有进程还需要资源的情况。
- 可利用资源 Available:这是一个含有 m 个元素的数组,其中每一个元素代表一类可利用的资源情况。其初始值是系统所配置的全部可用资源的数目。 如果Available[j] = k,则表示系统中现有 Rj 类资源 k 个。
- 最大需求矩阵 Max:这是一个 n*m 的矩阵。它定义了系统中 n 个进程每一个对 m 类资源的最大需求。如果Max[i,j] = K,则表示进程i需要 Rj 类资源的最大数目为 K。
- 分配矩阵 Allocation:这也是一个 n*m 矩阵,它定义了系统中每一类资源当前已分配给每一类进程的资源。如果Allocation[i.j]= K,则表示进程 i 已分得 Rj 类资源的数目为 K。
- 需求矩阵 Need:这也是 n*m 的矩阵,用来表示每一个进程尚需的各类资源数,如果Need[i,j]=K,则表示进程 i 还需要 K 个 Rj 类资源才能完成任务。
上述三个矩阵之间存在如下关系:Need[i, j] = Max[i, j] - Allocation[i, j]。
3. 银行家算法
4. 安全性算法
- 数据结构
- 工作向量 Work,它表示可以提供给进程继续运行所需要的各类的资源数目,它含有 m 个元素,在执行安全算法开始时,Work = Available;
- Finish,它表示系统是否有足够的资源分配给进程,使之运行完成。开始先做Finish[i] = false。当有足够资源分配给进程时,再令 FInish[i] = false;
- 算法思想
- a.从进程集合中找到一个满足下述条件的进程:
- Finish[i] = false;
- Need[i,j]<=Work[j];
- 如果找到执行步骤 b,否则执行步骤 c;
- b.当进程 Pi 获得资源后,可顺利执行,直到完成,并释放它的资源。故应执行:
- Work[j] = Work[j] + Allocation[i,j];
- Finish[j] =true;
- 返回执行步骤 a
- c.如果所有进程的 Finish[i] = true 都满足,则表示系统处于安全状态;否则,系统处于不安全状态。
- a.从进程集合中找到一个满足下述条件的进程:
5. 银行家算法举例
四、检测死锁
检测死锁算法用于检测系统状态,来确定系统中是否发生了死锁。
1. 资源分配图
- 系统死锁,可利用资源分配图来描述。
- 该图是由一组结点N和一组边E所组成的一个对偶G = (N, E),它具有下述形式的定义和限制:
- 把N分为两个互斥的子集,即一组进程结点P={ P1, P2, …, Pn}和一组资源结点R={R1, R2,…, Rn},N = P∪R。在下图所示的例子中,P = {P1, P2},R = {R1, R2},N = {P1, P2}∪{R1, R2}}。
- 凡属于E中的一个边e∈E,都连接着P中的一个结点和R中的一个结点,e = {Pi, Rj}是资源请求边,由进程Pi指向资源Rj,它表示进程Pi请求一个单位的Rj资源。E = {Rj,Pi}是资源分配边,由资源Rj指向进程Pi,它表示把一个单位的资源Rj分配给进程Pi。下图中示出了两个请求边和两个分配边,即E = {(P1, R2), (R2, P2), (P2, R1), (R1, P1)}。
2. 死锁定理
- 我们可以利用把资源分配图加以简化的方法,来检测当系统处于S状态时,是否为死锁状态。简化方法如下:
- 在资源分配图中,找出一个既不阻塞又非独立的进程结点Pi。在顺利的情况下, Pi 可获得所需资源而继续运行,直至运行完毕,再释放其所占有的全部资源,这相当于消去Pi的请求边和分配边,使之成为孤立的结点。在图(a)中,将P1的两个分配边和一个请求边消去,便形成图(b)所示的情况。
- P1 释放资源后,便可使 P2 获得资源而继续运行,直至 P2 完成后又释放出它所占有的全部资源,形成©所示的情况,即将P2 的两条请求边和一条分配边消去。
- 在进行一系列的简化后,若能消去图中所有的边,则称该图是可以完全简化的;如果不能消去所有的边,则称该图是不可完全简化的。
- S状态为死锁状态的充分条件:当且仅当S状态的资源分配图是可以完全简化的。该充分条件被称为“死锁定理”。
3.检测死锁算法
死锁检测中的数据结构类似于银行家算法中的数据结构:
- 可利用资源向量Available,它表示了m类资源中每一类资源的可用数目。
- 把不占用资源的进程(向量Allocation=0)记入L表中,即Li∪L。
- 从进程集合中找到一个Requesti≤Work的进程,做如下处理:①将其资源分配图简化,释放出资源,增加工作向量Work =Work + Allocation i。② 将它记入L表中。
- 若不能把所有进程都记入L表中,便表明系统状态S的资源分配图是不可完全简化的。因此,该系统状态将发生死锁。
五、解除死锁
如果利用死锁检测算法检测已经发生死锁。则应该立即采取相应的措施,来解除死锁,即利用解除死锁算法来解除算法。常用来解除死锁的两种方法:
- 抢占资源,从一个或多个进程抢占足够的资源,分配给死锁进程,来解除死锁状态。
- 终止(或撤销)进程,终止(或撤销)系统中一个或者多个死锁进程,直至打破循环环路,使系统从死锁状态解脱出来。