总结--死锁--面试中高频考点

死锁的概念

在多道程序系统中,由于多个进程的并发执行,改善了系统资源的利用率并提高了系统的处理能力。然而,多个进程的并发执行也带来了新的问题-----死锁。
当多个进程因竞争系统资源或相互通信而处于永久阻塞状态时,若无外力作用,这些进
程都将无法向前推进。这些进程中的每一个进程,均无限期地等待此组进程中某个其他进程占有的、自己永远无法得到的资源,这种现象称为死锁。
下面通过几个例子来说明死锁现象。
某系统中只有一台打印机和一台输入设备,进程P1正在占用输入设备,同时又提出了使用打印机的请求,但此时打印机正被进程P2占用。而P2在未释放打印机之前,又提出请求使用正被P1占用着的输入设备。这样,两个进程相互无休止地等待下去,均无法继续执行, 此时两个进程陷入死锁状态。
在生产者一消费者问题中,如果交换生产者进程中的两个P操作的顺序,则有可能出现死锁。改动后的生产者一消费者问题描述如下:

Semaphore full = 0;			//满缓冲区的数目
Semaphore empty = n;			//空缓冲区的数目
Semaphore mutex = 1;			//对有界缓冲区进行操作的互斥信号量
Buffer array[0,…,n-1];			//存放产品的缓冲区
Int in=0,out=0;					//缓冲池的指针,只是生产者和消费者的存取位置
Producer()
{
	while(true)
	{
		Produce an item put in nextp;  	//nextp为临时缓冲区
		P(mutex);						//此处调换顺序
		P(empty);						//此处调换顺序
		Buffer(in)=nextp;				//将产品放入缓冲池
		in=(in+1)%n;				//指针后移
		V(mutex);						//缓冲池使用完毕,释放互斥信号量
		V(full);						//增加一个满缓冲区
	}
}
Consumer()
{
	while(true)
	{
		P(full);						//申请一个满缓冲区
		P(mutex);						//申请使用缓冲区
		nextc = buffer(out);			//取出产品
		out=(out+1)%n;					//指针后移
		V(mutex);						//缓冲池使用完毕,释放互斥信号量
		V(empty);						//增加一个空缓冲区
		Consumer the item in nextc; 	//消费掉产品
	}
}

交换生产者进程中两个P操作的次序,一般情况下不会出现死锁,但在特殊情况下会出现死锁。例如,在某一时刻缓冲区中已装满了产品且缓冲区中没有进程工作〔这时信号量full的值为n,信号量empty的值为0,信号量mutex的值为1〕,若系统此时调度生产者进程运行,生产者进程生产了一个产品,执行P(mutex)并顺利进入临界区(这时mutex的值为0), 随后它执行P(empty)时因没有空闲缓冲区而受阻等待,等待消费者进程进入缓冲区取走产品以释放出缓冲区;消费者进程执行P(full)后再执行P(mutex)时,因缓冲区被生产者进程占据而无法进入。这样就形成了生产者进程在占有临界资源的情况下等待消费者进程取走产品,而消费者进程又无法进入临界区取走产品的僵局,此时两进程陷入死锁。
可以由死锁的定义和上述例子得到如下结论。
● 参与死锁的进程至少有两个。
● 每个参与死锁的进程均等待资源。
● 参与死锁的进程中至少有两个进程占有资源。
● 死锁进程是系统中当前进程集合的一个子集。

死锁产生的原因和必要条件

(1)资源分类

操作系统是一个资源管理程序,它负责分配不同类型的资源给进程使用。现代操作系统所管理的资源类型十分丰富,并且可以从不同的角度出发对其进行分类。例如,可以把资源分为可剥夺资源和不可剥夺资源。
可剥夺资源是指虽然资源占有者进程仍然需要使用该资源,但另一个进程可以强行把该资源从占有者进程处剥夺来归自己使用。
不可剥夺资源是指除占有者进程不再需要使用该资源而主动释放资源外,其他进程不得在占有者进程使用资源过程中强行剥夺。
一个资源是否属于可剥夺资源,完全取决于资源本身的性质。比如打印机在一个打印任务未结束之前,是无法被其他打印任务剥夺的,属于不可剥夺资源;而主存和CPU却是可剥夺资源。
在研究资源分配时,必须弄清资源的类型,资源的不同使用性质是引起系统死锁的原因。如对可剥夺资源的竞争不会引起进程死锁,而对其他类型资源的竞争则有可能导致死锁。

(2)死锁产生的原因

死锁产生的原因是竞争资源。如果系统中只有一个进程在运行,所有资源为一个进程独享,则不会出现死锁现象。当系统中有多个进程并发执行时,若系统中的资源不足以同时满足所有进程的需要,则会引起进程对资源的竞争,从而可能导致死锁的产生。图2-9给出了两个进程竞争资源的情况。
在这里插入图片描述

在图2-9中,假定进程P1和P2分别申请到了资源A和资源B,现在进程P1又提出使用资源B的申请,由于资源B已被进程P2占有,所以进程P1阻塞;而进程P2可以继续运行,进程P2在运行中又提出使用资源A的申请,由于资源A已经被进程P1占有,所以进程P2阻塞。于是进程P1、P2都因资源得不到满足而进入阻塞状态,而进程陷入死锁。
虽然资源竞争可能导致死锁,但是资源竞争并不等于死锁,只有在进程运行过程中请求和释放资源的顺序不当时(即进程的推进顺序不当时),才会导致死锁。在图2-9中,若进程P1和P2按照下列顺序执行:P1申请A,P1申请B,P1释放A,P1释放B,P2申请B,P2申请A,P2释放B,P2释放A,则两个进程均可顺利完成,不会发生死锁。图2-10中的路径①表示了这种情况。类似地,若按照路径②和③所示的顺序推进也不会产生死锁,但按照路径④所示的顺序推进则会产生死锁。
在这里插入图片描述

图中的路径③与路径①的结果是相同的,区别在于P2申请B时P1还未释放B,所以P2組塞,直到P1释放B之后才唤醒继续执行。
由此可知,死锁产生的原因是系统资源不足和进程推进顺序不当。
系统资源不足是根本原因,设计操作系统的目的就是使并发进程共享系统资源。而进程推进顺序不当是产生死锁的重要原因,当系统资源刚好够进程使用时,进程的推进顺序不当就很容易导致进程彼此占有对方需要的资源,从而导致死锁。

(3)死锁产生的必要条件

从上面的论述中可以推出,发生死锁的必要条件有以下4条。
● 互斥条件。进程要求对所分配的资源进行排他性控制,即在一段时间内某种资源仅为一个进程所占有。
● 不剥夺条件。进程所获得的资源在未使用完毕之前,不能被其他进程强行夺走,即只能由获得该资源的进程自己来释放。
● 请求与保持条件。进程每次申请它所需的一部分资源。在等待分配新资源的同时, 进程继续占有己经分配到的资源。请求与保持条件也称为部分分配条件。
● 环路等待条件。存在一种进程资源的循环等待链,而链中的每一个进程已经获得的资源同时被链中下一个进程所请求。
要发生死锁,这4个条件缺一不可,因此可以通过破坏其中的一个或几个条件来避免死锁的发生。

处理死锁的基本方法

目前用于处理死锁的方法主要有以下4种。
● 鸵鸟算法。指像鸵鸟一样对死锁视而不见,即不理睬死锁。
● 预防死锁。通过设置某些限制条件,去破坏产生死锁的4个必要条件中的一个或几个来预防发生死锁。
● 避免死锁。在资源的动态分配过程中,用某种方法防止系统进入不安全状态,从而避免死锁。
● 检测及解除死锁。通过系统的检测机构及时地检测出死锁的发生,然后采取某种措施解除死锁。
这里要注意区分后3种措施的不同之处。预防死锁是在调度方式上破坏死锁产生的必要条件,使系统无法产生死锁,例如釆用可剥夺式的进程调度方法,优先级高的进程总能得到资源并完成运行,因此系统不会产生死锁;避免死锁是在动态分配过程中,预知系统是否会进入不安全状态,如果该资源分配有可能产生死锁,则不进行这种分配,后面要讲到的银行家算法就是一种避免死锁的方法;而检测及解除死锁是一种比较被动的方法,是在检测到死锁己经发生之后进行处理,例如采用剥夺死锁进程的资源等方法强制进程释放资源或结束死锁进程来解除死锁状态。
这3种方法有不同的特点,例如在不能够破坏死锁必要条件的情况下,就无法采用预防死锁的方法,只能够采用其他方法;在系统进程过多,预测系统是否进入不安全状态的成本过高时,采用避免死锁的方法并不划算,不如等死锁发生后采用检测及解除死锁的方法。
现实中的操作系统并非都采用以上3种处理方法,相反,很多操作系统认为死锁不可能发生,对死锁不进行任何处理(这种说法不够积极,应该是对死锁采用鸵鸟算法),如UNIX.。
★注意:死锁避免和死锁预防不是同一个概念。
死锁预防和死锁避免采取的措施都是在死锁发生之前,但是它们之间还是有很大区别的。死锁预防对系统加的限制条件通常很严格,对系统的并发性会产生很大的副作用,此后就不需要再运行什么算法来计算死锁发生的可能性;死锁避免对系统所加的限制条件则相对宽松,有利于进程的并发执行,但是死锁避免往往在资源被分配出去之前要计算分配之后系统是否安全。
这里将死锁检测和死锁解除归为一种方法,有些资料上将这两种分开作为不同的解决死锁的策略,因此也有4种方法,其实是直接无视了鸵鸟算法而己。

死锁的预防

根据以上讨论,要想防止死锁的发生,只需破坏死锁产生的4个必要条件之一即可。下面具体分析与这4个条件相关的技术。

(1)互斥条件

为了破坏互斥条件,就要允许多个进程同时访问资源。但是这会受到资源本身固有特性的限制,有些资源根本不能同时访问,只能互斥访问。如打印机就不允许多个进程在其运行期间交替打印数据,只能互斥使用。由此看来,通过破坏互斥条件来防止死锁的发生是不大可能的。

(2)不剥夺条件

为了破坏不剥夺条件,可以制定这样的策略:对于一个已经获得了某些资源的进程,若新的资源请求不能立即得到满足,则它必须释放所有已经获得的资源,以后需要资源时再重新申请。这就意味着,一个进程已获得的资源在运行过程中可以被剥夺,从而破坏了不剥夺条件。该策略实现起来比较复杂,释放已获得资源可能造成前一段工作的失效,重复申请和释放资源会增加系统开销,降低系统吞吐量。这种方法通常不会用于剥夺资源之后代价较大的场合,比如不会用于对打印机的分配,在一个进程正在打印时,不会采用剥夺的方法来解除死锁。

(3)请求与保持条件

为了破坏请求与保持条件,可以采用预先静态分配方法。预先静态分配法要求进程在其运行之前一次性申请它所需要的全部资源,在它的资源未满足前,不把它投入运行。一旦投入运行后,这些资源就一直归它所有,也不再提出其他资源请求,这样就可以保证系统不会发生死锁。这种方法既简单又安全,但降低了资源利用率。釆用这种方法必须事先知道该作业(或进程)所需要的全部资源。即使有的资源只能在运行后期使用,甚至有的资源在正常运行中根本不用,也不得不预先统一申请,结果使得系统资源不能充分利用。
以打印机为例,一个作业可能只在最后完成时才需要打印计算结果,但在作业运行前就把打印机分配给它,那么在作业整个执行过程中打印机基本处于闲置状态。

(4)环路等待条件

为了破坏环路等待条件,可以采用有序资源分配法。有序资源分配法是将系统中的所有资源都按类型赋予一个编号〔例如打印机为1,磁带机为2等),要求每一个进程均严格按照编号递增的次序请求资源,同类资源一次申请完。也就是说,只要进程提出请求资源Ri,则在以后的请求中只能请求排在Ri后面的资源(i为资源编号),不能再请求编号排在Ri前面的资源。对资源请求作了这种限制后,系统中不会再出现几个进程对资源的请求形成环路的情况。
这种方法由于对各种资源编号后不宜修改,从而限制了新设备的增加;不同作业对资源使用的顺序也不会完全相同,即便系统对资源编号考虑到多数情况,但总会有与系统编号不符的作业,从而造成资源浪费;对资源按序使用也会增加程序编写的复杂性。

死锁的避免

预防死锁方法中所采用的几种策略,总的来说都施加了较强的限制条件,虽然实现起来较为简单,但却严重损害了系统性能。在避免死锁的办法中,所施加的限制条件较弱,有可能获得较好的系统性能。在该方法中把系统的状态分为安全状态和不安全状态,只要能使系统始终处于安全状态,便可以避免死锁的发生。

(1)安全状态与不安全状态

在避免死锁的方法中,允许进程动态地申请资源,系统在进行资源分配之前,先计算资源分配的安全性。若此次分配不会导致系统进入不安全状态,便将资源分配给进程,否则进程必须等待。
若在某一时刻,系统能按某种顺序来为每个进程分配其所需的资源,直至最大需求,使每个进程都可顺利完成,则称此时的系统状态为安全状态,称该序列为安全序列。若某一时刻系统中不存在这样的一个安全序列,则称此时的系统状态为不安全状态。需要注意的是,安全序列在某一时刻可能并不唯一,即可以同时存在多种安全序列。
虽然并非所有的不安全状态都是死锁状态,但当系统进入不安全状态后,便可能进入死锁状态;反之,只要系统处于安全状态,系统便可避免进入死锁状态。
★注意:以下两点是常犯的混淆性错误,希望大家注意。
● 不安全状态不是指系统中己经产生死锁。认为不安全状态就是死锁的观点错在不知道不安全状态是指系统可能发生死锁的状态,并不意味着系统已经发生死锁。
● 处于不安全状态的系统不会必然导致死锁。对系统进行安全性检测的时候是根据进程的最大资源需求而定的,而实际运行过程中进程可能不需要那么多的资源,所以哪怕系统进入了不安全状态也不一定会导致死锁。而且实际系统运行过程中,有些占有资源并没有执行完的进程可能主动放弃资源,这也会使得处于不安全状态的系统不产生死锁。死锁是不安全状态的真子集。

(2)银行家算法

具有代表性的避免死锁算法,是Dijkstra给出的银行家算法。为实现银行家算法,系统中必须设置若干数据结构。假定系统中有n个进程(P1,P2,…Pn),m类资源(R1,R2,…,Rm),银行家算法中使用的数据结构如下:
● 可利用资源向量Available:这是一个含有m个元素的数组,其中Available[i]的值表示第i类资源的现有空闲数量,其初始值为系统中所配置的该类资源的数目。其数值随着该类资源的分配和回收而动态改变。
● 最大需求矩阵Max:这是一个n×m的矩阵,它定义了系统中每一个进程对m类资源的最大需求数目,Max[i][j]的值表示第i个进程对第j类资源的最大需求。
● 分配矩阵Allocation:这也是一个n×m的矩阵,它定义了系统中每一类资源当前己经分配给每一个进程的资源数目。Allocation[i][j]的值表示第i个进程当前拥有的第j类资源的数量。
● 需求矩阵Need:这同样是一个n×m的矩阵,它定义了系统中每个进程还需要的各类资源数目〔注意,是“还需要”,不是“总需要”,表示此矩阵也是变化的)。Need[i][j]的值表示第i个进程还需要的第j类资源的数量。向量Needi是矩阵Need的第i行,是进程i的需求资源向量。
★上述的n×m的矩阵三兄弟具有如下关系:
Need[i][j] = Max[i][j]-Allocation[i][j]
银行家算法的描述如下:
定义Requesti向量:Requesti表示第i个进程向系统提出一次申请,申请的各类资源的数量就是该向量的各个分量。
当进程Pi向系统发出资源请求后,系统进行如下操作:
1)若Requesti ≤Needi,那么跳至2)。否则报错,因为进程Pi申请的资源数不应该超过它的需求数。
2)若Requesti ≤Availablei,那么跳至3),否则Pi进程需要等待,因为可用资源不够。
3)对Pi进程所请求的资源进行预分配,修改以下向量:
Available = Available – Requesti;
Allocationi = Allocationi + Requesti
Needi = Needi – Requesti
4)对于修改后的向量调用安全性算法。若安全性算法返回系统处于安全状态,则按Requesti表示的资源数量给Pi进程分配资源;若安全性算法返回系统处于不安全状态,则不分配给Pi进程任何资源,让Pi等待,并恢复3)中所改变的向量。
在这里插入图片描述

安全性算法描述如下:
1)建立长度为m的向量Work和长度为n的向量Finish,并对他们进行如下初始化:Work=Available;Finish[i]=false;(i=1,2,…,n).
2)查找满足如下两个条件的i:
Finish[i] = false; Needi ≤Work;
若没有这样的i存在,则跳到4)执行。
3)进行如下操作:
Work = Work + Allocationi
Finish[i] = true
返回到2)。
4)如果对于所有的i,都有Finish[i] = true,那么系统处于安全状态,否则为不安全状态。安全性算法的时间复杂度达到了 O(m × n2 )。

安全性算法流程图如图2-12所示。
银行家算法举例如下。

假定系统中有4个进程P1、P2、P3、P4,3种类型的资源R1、R2、R3,数量分别为9、3、6,T0时刻的资源分配情况见表2-1。
试问:1)T0时刻是否安全?
2) T0时刻以后,若进程P2发出资源请求Request2(1,0,1),系统能否将资源分配给它?
在这里插入图片描述

3)在进程P2申请资源后,若P1发出资源请求Request1(1,0,1),系统能否将资源分配给它?
4)在进程P1申请资源后,若P3发出资源请求Request3(0,0,1),系统能否将资源分配给它?
解:
1)T0时刻的安全性:利用安全性算法对T0时刻的资源分配情况进行分析,可得到表2-2所示的安全性分析。从中得知,T0时刻存在安全序列{P2,P1,P3,P4},故系统是安全的。

2)P2请求资源Request2(1,0,1),系统按银行家算法进行检查,执行如下操作:
● Request2(1,0,1)≤ Need2(1,0,2).
● Request2(1,0,1)≤ Available(1,1,2).
● 系统假定为P2分配资源,并修改Available、Allocation2、Need2向量,由此形成的资源变化情况见表2-3。
● 再利用安全性算法检查此时系统是否安全,可得安全性分析结果见表2-4。
由结果可知,可以找到一个安全序列{P2,P1,P3,P4},因此系统是安全的,可以将资源分配给P2.
在这里插入图片描述

3)P1请求资源Request1(1,0,1),系统按银行家算法进行检查,执行如下操作:
● Request1 (1,0,1) ≤ Need1(2,2,2)。
● Request1 (1,0,1) > Available(0,1,1)。
● 因此P1需要等待,不能将资源分配给P1。
4)P3请求资源Request3(0,0,1),系统按银行家算法进行检查,执行如下操作:
● Request3 (0,0,1) ≤ Need1(1,0,3)。
● Request3 (0,0,1) ≤ Available(0,1,1)。
● 系统假定为P3分配资源,并修改Available、Allocation3、Need3向量,由此形成的资源变化情况见表2-5。
在这里插入图片描述

● 表2-5可知,Available(0,1,0)已经不能满足任何进程的需要,系统进入不安全状态, 因此系统不能将资源分配给P3。

死锁的检测和解除

前面介绍的死锁预防和避免算法都是在系统为进程分配资源时施加限制条件或进行检测,若系统为进程分配资源时不采取任何措施,则应该提供检测和解除死锁的方法。

(1)死锁检測

1)资源分配图
进程的死锁问题可以用有向图更加准确而形象地描述,这种有向图称为系统资源分配图。一个系统资源分配图(System Resource Allocation Graph)可定义为一个二元组,即SRAG=(V,E),其中V是顶点的集合,而E是有向边的集合。顶点集合可分为两部分:P=(P1,P2,…,Pn),是由系统内的所有进程组成的集合,每一个Pi(i=1,2,…,n)代表一个进程;R=(r1,r2,…,rm),是系统内所有资源组成的集合,每一个ri(i=1,2,…,m)代表一类资源。
有向边集合E中的每一条边是一个有序对<Pi,ri>或<ri,Pi>。<Pi,ri>∈E表示存在一条从Pi指向ri的有向边,它的含义是Pi请求一个ri资源,并且当前尚未分配。<ri,Pi>∈E表示存在一条从ri指向Pi的有向边,它的含义是ri类资源中的一个资源已分配给进程Pi。有向边<Pi,ri>叫做申请边,而有向边<ri,Pi>则叫做分配边。
在SRAG中,用圆圈代表进程,用方框表示每类资源。每一类资源ri可能有多个,可用方框中的圆圈表示各个资源。申请边是从进程到资源的有向边,表示进程申请一个资源,但当前该进程尚未得到该资源。分配边是从资源到进程的有向边,表示有一个资源分配给进程。一条申请边仅指向代表资源类ri的方框,表示申请时不指定哪一个具体资源。
当进程Pi申请资源类ri的一个资源时,将一条申请边加入资源分配图,如果这个申请是可以满足的,则该申请边立即转换成分配边;当进程随后释放了某个资源时,则删除分配边。
以图2-13为例进行讲解。
集合P,R,E分别为:P={P1,P2}, R={r1,r2},
E={<P1,r2>,<P2,r1>,<r1,P1>,<r1,P1>,<r1,P2>
,<r2,P2>}
当前状态如下:
● 进程P1已占用两个r1资源,而且正在申请获得一个r2资源。
● 进程P2已占用一个r1资源和一个r2资源,而且正在申请获得一个r1资源。
2) 死锁定理
可以用将资源分配图简化的方法来检测系统状态S是否是死锁状态。简化方法如下:
● 在资源分配图中,找出一个既不阻塞又非孤立的进程节点Pi(即从进程集合中找到一个存在连接的边,且资源申请数量小于系统中已有空闲资源数量的进程)。因进程Pi获得了所需要的全部资源,它能继续运行直到完成,然后释放其所占有的所有资源。这相当于消去Pi的所有申请边与分配边,使之成为孤立的节点。
● 进程Pi释放资源后,可以唤醒因等待这些资源而阻塞的进程,原来阻塞的进程可能变为非阻塞进程,根据第一步中的简化方法消去分配边与申请边。
● 重复前两步的简化过程后,若能消去图中所有的边,使所有进程成为孤立节点,则称该图是可完全简化的;若不能通过任何过程使该图完全简化,则称该图是不可完全简化的。
可以证明所有的简化顺序将得到相同的不可简化图。S为死锁状态的条件是当且仅当S状态的资源分配图是不可完全简化的。该定理称为死锁定理。

(2)死锁检测算法

发现死锁的原理是考査某一时刻系统状态是否合理,即是否存在一组可以实现的系统状态,能使所有进程都得到它们所申请的资源而运行结束。检测死锁算法的基本思想是:获得某时刻t系统中各类可利用资源的数目向量available(t),对于系统中的一组进程{P1,P2,…,Pn},找出那些对各类资源请求数目均小于系统现有的各类可利用资源数目的进程。这样的进程可以获得它们所需要的全部资源并运行结束,当它们运行结束后释放所占有的全部资源,从而使可用资源数目增加,将这样的进程加入到可运行结束的进程序列中,然后对剩下的进程再进行上述考查。如果一组进程中有几个不属于该序列,那么它们会发生死锁。
与银行家算法和安全性算法类似,死锁检测算法也需要几个数据结构。
● Available:表示当前可用资源的向量。
● Allocation:表示已经分配的资源矩阵。
● Request:表示进程请求资源的矩阵。
● 临时变量:Work与Finish两个向量,作用和安全性算法中相同。
死锁检测算法如图2-14所示。

检测死锁可以在每次分配资源后进行。但是,用于检测死锁的算法比较复杂,所需的检测时间长,系统开销大,因此也可以选取比较长的时间间隔来执行。

(3)死锁解除

一旦检测出系统中出现了死锁,就应将陷入死锁的进程从死锁状态中解脱出来,常用的解除死锁方法有两种:
● 剥夺资源:从其他进程中抢占足够的资源给死锁的进程以解除其死锁状态。
● 撤销进程:撤销一些进程,直到有足够的资源以分配给其他进程,解除死锁状态。

死锁与饿死

死锁、饥饿、饿死通常是容易混淆的概念,这里特别说明一下。
在一个动态系统中,资源请求与释放是经常发生的进程行为。对于每类系统资源,操作系统需要确定一个分配策略,当多个进程同时申请某类资源时,由分配策略确定资源分配给进程的次序。资源分配策略可能是公平的,能保证请求者在有限的时间内获得所需资源;资源分配策略也可能是不公平的,即不能保证等待时间上界的存在。在后一种情况下,即使系统没有发生死锁,某些进程也可能会长时间等待。当等待时间给进程推进和响应带来明显影响时,则称此时发生了进程饥饿,当饥饿到一定程度的进程所赋予的任务即使完成也不再具有实际意义时,称该进程被饿死
考虑一台打印机分配的例子,当有多个进程需要打印文件时,系统按照短作业优先〔SJF的策略排序,该策略具有平均等待时间短的优点,似乎非常合理,但当短文件打印任务源源不断时,长文件的打印任务将被无限期推迟,导致饥饿以至饿死。
与饥饿相关的另外一个概念是活锁。在忙式等待条件下发生的饥饿,称为活锁,例如不公平的互斥算法。虽然此时进程仍然在执行,但有些进程由于无法调度执行,好像发生了死锁一样。
饿死与死锁有一定联系:二者都是由于竞争资源而引起的,但又有明显差别,主要表现在如下几个方面。
● 从进程状态考虑,死锁进程都处于等待状态;忙式等待(处于运行或就绪状态)的进程并非处于等待状态,但却可能被饿死。
● 死锁进程等待的是永远不会被释放的资源;而饿死进程等待的是会被释放但却不会分配自己的资源,表现为等待时限没有上界(排队等待或忙式等待)。
● 死锁一定发生了循环等待,而饿死则不然。这也表明通过资源分配图可以检测死锁存在与否,但却不能检测是否有进程饿死。
● 死锁一定涉及多个进程,而饥饿或被饿死的进程可能只有一个。
饥饿和饿死与资源分配策略有关,因而防止饥饿与饿死可从公平性考虑,确保所有进程不被忽视,如多级反馈队列调度算法。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SS_zico

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值