死锁的产生及避免

1. 死锁

死锁可以被定义成一组竞争系统资源或互相通信的进程间相互的“永久”阻塞。当一组进程中的所有进程都在等待一个事件,而只有在进程集合中的其他阻塞的进程才可以触发该事件,这时就称一组进程死锁。

2. 产生死锁的四个必要条件 

(1) 互斥条件:一个资源每次只能被一个进程使用。 

(2) 占有且等待条件:一个 进程因请求资源而阻塞时,对已获得的资源保持不放。 

(3) 不剥夺条件(非抢占):   进程已获得的资源,在末使用完之前,不能强行剥夺。 

(4) 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。

 这四个条件连在一起是死锁的充分必要条件,只要系统发生死锁,这些条件必然成立,而只要上述条件之一不满足,就不会发生死锁。

理解了死锁的原因,尤其是产生死锁的四个必要条件,就可以最大可能地避免、预防和解除死锁。所以,在系统设计、进程调度等方面注意如何不让这四个必要条件成立,如何确定资源的合理分配算法,避免进程永久占据系统资源。此外,也要防止进程在处于等待状态的情况下占用资源。因此,对资源的分配要给予合理的规划。 

3. 死锁预防

(1)互斥  

一般来说,互斥条件不可能禁止。

(2)占有且等待

为了预防请求占有且等待的条件,可以要求进程一次性的请求所有需要的资源,并且阻塞这个进程直到所有请求都同时满足。但是这种方法是低效的。

(3)不剥夺

如果占有某些资源的一个进程进行进一步资源请求被拒绝,则该进程必须释放它最初占有的资源,如果有必要,可再次请求这些资源和另外的资源。另一种方法是,如果一个进程请求当前被另一个进程占有的一个资源,则操作系统可以抢占另一个进程,要求他释放资源。但是这种方法只适用于两个进程不具有相同的优先级时才能预防。

(4)循环等待

可以通过定义资源的线性顺序来预防。但是会使进程执行速度变慢,并且可能在没必要的情况下拒绝资源访问。

4.死锁避免

(1)如果一个进程的请求会导致死锁,则不启动此进程。

(2)如果一个进程增加资源的请求会导致死锁,则不允许此分配。

5.常见的避免/处理死锁的方法:  

(1) 加锁顺序 

当多个线程需要相同的一些锁,但是按照不同的顺序加锁,死锁就很容易发生。 如果能确保所有的线程都是按照相同的顺序获得锁,那么死锁就不会发生。 按照顺序加锁是一种有效的死锁预防机制。但是,这种方式需要你事先知道所有可能会用到的锁,但总有些时候是无法预知的。  

(2) 加锁时限 

另外一个可以避免死锁的方法是在尝试获取锁的时候加一个超时时间,这也就意味着在尝试获取锁的过程中若超过了这个时限该线程则放弃对该锁请求。若一个线程没有在给定的时限 内成功获得所有需要的锁,则会进行回退并释放所有已经获得的锁,然后等待一段随机的时 间再重试。这段随机的等待时间让其它线程有机会尝试获取相同的这些锁,并且让该应用在没有获得锁的时候可以继续运行(加锁超时后可以先继续运行干点其它事情,再回头来重复之前加锁的逻辑)。 

(3) 死锁检测 

死锁检测是一个更好的死锁预防机制,它主要是针对那些不可能实现按序加锁并且锁超时也不可行的场景。 

每当一个线程获得了锁,会在线程和锁相关的数据结构中(map、graph 等等)将其记下。 除此之外,每当有线程请求锁,也需要记录在这个数据结构中。 当一个线程请求锁失败时,这个线程可以遍历锁的关系图看看是否有死锁发生。例如,线程 A 请求锁 7,但是锁 7 这个时候被线程 B 持有,这时线程 A 就可以检查一下线程 B 是否已经请求了线程 A 当前所持有的锁。如果线程 B 确实有这样的请求,那么就是发生了死锁(线程 A 拥有锁 1,请求锁 7;线程 B 拥有锁 7,请求锁 1)。 

当然,死锁一般要比两个线程互相持有对方的锁这种情况要复杂的多。线程 A等待线程 B, 线程 B 等待线程 C,线程 C 等待线程 D,线程 D又在等待线程 A。线程 A 为了检测死锁,它 需要递进地检测所有被 B请求的锁。从线程 B 所请求的锁开始,线程 A 找到了线程 C,然后 又找到了线程 D,发现线程 D请求的锁被线程 A自己持有着。这是它就知道发生了死锁。  

当检测出死锁时,一个可行的做法是释放所有锁,回退,并且等待一段随机的时间后重试。这个和简单的加锁超时类似,不一样的是只有死锁已经发生了才回退,而不会是因为加锁的请求超时了。虽然有回退和等待,但是如果有大量的线程竞争同一批锁,它们还是会重复地死锁(原因同超时类似,不能从根本上减轻竞争)。 

一个更好的方案是给这些线程设置优先级,让一个(或几个)线程回退,剩下的线程就像没发生死锁一样继续保持着它们需要的锁。如果赋予这些线程的优先级是固定不变的,同一批线程总是会拥有更高的优先级。为避免这个问题,可以在死锁发生的时候设置随机的优先级。

6. 一种综合的死锁策略

(1)把资源分成几组不同资源类。

(2)为预防在资源类之间由于循环等待产生死锁,可使用线性排序的策略。

(3)在一个资源类中,使用该资源类最适合的算法。 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值