什么是死锁有什么处理及排除方法(2)
4)竞争临时资源
上面所说的打印机资源属于可顺序重复使用型资源,称为永久资源。还有一种所谓的临时资源,这是指由一个进程产生,被另一个进程使用,短时间后便无用的资源,故也称为消耗性资源,如硬件中断、信号、消息、缓冲区内的消息等,它也可能引起死锁。例如,SI,S2,S3是临时性资源,进程P1产生消息S1,又要求从P3接收消息S3;进程P3产生消息S3,又要求从进程P2处接收消息S2;进程P2产生消息S2,又要求从P1处接收产生的消息S1。如果消息通信按如下顺序进行:
P1: ···Relese(S1);Request(S3); ···
P2: ···Relese(S2);Request(S1); ···
P3: ···Relese(S3);Request(S2); ···
并不可能发生死锁。但若改成下述的运行顺序:
P1: ···Request(S3);Relese(S1);···
P2: ···Request(S1);Relese(S2); ···
P3: ···Request(S2);Relese(S3); ···
则可能发生死锁。
2.进程推进顺序不当引起死锁
由于进程在运行中具有异步性特征,这可能使P1和P2两个进程按下述两种顺序向前推进。
1) 进程推进顺序合法
当进程P1和P2并发执行时,如果按照下述顺序推进:P1:Request(R1); P1:Request(R2); P1: Relese(R1);P1: Relese(R2); P2:Request(R2); P2:Request(R1); P2: Relese(R2);P2: Relese(R1);这两个进程便可顺利完成,这种不会引起进程死锁的推进顺序是合法的。
2) 进程推进顺序非法
若P1保持了资源R1,P2保持了资源R2,系统处于不安全状态,因为这两个进程再向前推进,便可能发生死锁。例如,当P1运行到P1:Request(R2)时,将因R2已被P2占用而阻塞;当P2运行到P2:Request(R1)时,也将因R1已被P1占用而阻塞,于是发生进程死锁。
死锁处理方法
在系统中已经出现死锁后,应该及时检测到死锁的发生,并采取适当的措施来解除死锁。[4]
1) 预防死锁。
这是一种较简单和直观的事先预防的方法。方法是通过设置某些限制条件,去破坏产生死锁的四个必要条件中的一个或者几个,来预防发生死锁。预防死锁是一种较易实现的方法,已被广泛使用。但是由于所施加的限制条件往往太严格,可能会导致系统资源利用率和系统吞吐量降低。
2) 避免死锁。
该方法同样是属于事先预防的策略,但它并不须事先采取各种限制措施去破坏产生死锁的的四个必要条件,而是在资源的动态分配过程中,用某种方法去防止系统进入不安全状态,从而避免发生死锁。
3)检测和解除死锁。
先检测:这种方法并不须事先采取任何限制性措施,也不必检查系统是否已经进入不安全区,此方法允许系统在运行过程中发生死锁。但可通过系统所设置的检测机构,及时地检测出死锁的发生,并精确地确定与死锁有关的进程和资源。检测方法包括定时检测、效率低时检测、进程等待时检测等。
然后解除死锁:采取适当措施,从系统中将已发生的死锁清除掉。
这是与检测死锁相配套的一种措施。当检测到系统中已发生死锁时,须将进程从死锁状态中解脱出来。常用的实施方法是撤销或挂起一些进程,以便回收一些资源,再将这些资源分配给已处于阻塞状态的进程,使之转为就绪状态,以继续运行。死锁的检测和解除措施,有可能使系统获得较好的资源利用率和吞吐量,但在实现上难度也最大。
死锁的排除方法
1、撤消陷于死锁的全部进程;
2、逐个撤消陷于死锁的进程,直到死锁不存在;
3、从陷于死锁的进程中逐个强迫放弃所占用的资源,直至死锁消失。
4、从另外一些进程那里强行剥夺足够数量的资源分配给死锁进程,以解除死锁状态
计算机网络的死锁
死锁是网络中最容易发生的故障之一,即使在网络负荷不很重时也会发生。死锁发生时,一组节点由于没有空闲缓冲区而无法接收和转发分组,节点之间相互等待,既不能接收分组也不能转发分组,并一直保持这一僵局,严重时甚至导致整个网络的瘫痪。此时,只能靠人工干预来重新启动网络,解除死锁。但重新启动后并未消除引起死锁的隐患,所以可能再次发生死锁。死锁是由于控制技术方面的某些缺陷所引起的,起因通常难以捉摸、难以发现,即使发现,也常常不能立即修复。因此,在各层协议中都必须考虑如何避免死锁的问题。
存储转发死锁及其防止
最常见的死锁是发生在两个节点之间的直接存储转发死锁。例如,A节点的所有缓冲区装满了等待输出到B节点的分组,而B节点的所有缓冲区也全部装满了等待输出到A节点的分组;此时,A节点不能从B节点接收分组,B节点也不能从A节点接收分组,从而造成两节点间的死锁。这种情况也可能发生在一组节点之间,例如,A节点企图向B节点发送分组、B节点企图向C节点发送分组、而C节点又企图向A节点发送分组,但此时每个节点都无空闲缓冲区用于接收分组,这种情形称做间接存储转发死锁。当一个节点处于死锁状态时,所有与之相连的链路将被完全拥塞。
一种防止存储转发死锁的方法是,每个节点设置M+1个缓冲区,并以0到M编号。M为通信子网的直径,即从任一源节点到任一目的节点间的最大链路段数。每个源节点仅当其0号缓冲区空时才能接收源端系统来的分组,而此分组仅能转发给1号缓冲区空闲的相邻节点,再由该节点将分组转发给它的2号缓冲区空闲的相邻节点……最后,该分组或者顺利到达目的节点并被递交给目的端系统,或者到了某个节点编号为M的缓冲区中再也转发不下去,此时一定发生了循环,应该将该分组丢弃。由于每个分组都是按照编号递增规则分配缓冲区,所以节点之间不会相互等待空闲缓冲区而发生死锁现象。这种方法的不足之处在于,当某节点虽然有空闲缓冲区,但正巧没有所需要的特定编号的缓冲区时,分组仍要等待,从而造成了缓冲区和链路的浪费。
另一种防止存储转发死锁的方法是,使每个分组上都携带一个全局性的惟一的"时间戳",每个节点要为每条输入链路保留一个特殊的接收缓冲区,而其它缓冲区均可用于存放中转分组。在每条输出链路的队列上分组按时间戳顺序排队。例如,节点A要将分组送到节点B,若B节点没有空闲缓冲区,但正巧有要送到A节点的分组,此时A、B节点可通过特殊的接收缓冲区交换分组;若B节点既没有空闲缓冲区,也没有要送往A节点的分组,B节点只好强行将一个出路方向大致与A节点方向相同的分组与A节点互相交换分组,但此时A节点中的分组必须比B节点中的分组具有更早的时间戳,这样才能保证子网中某个最早的分组不受阻挡地转发到目的地。由此可见,每个分组最终总会成为最早的分组,并总能被一步一步地发送到目的节点,从而避免了死锁现象的发生。
看过“死锁的处理方法”的人还看了: