避免死锁和死锁诊断

来源:互联网 发布:时间轴网站源码 编辑:程序博客网 时间:2024/06/05 12:00

 一般来说,要出现死锁必须同时具备四个条件。因此,如果能够尽可能地破坏这四个条件中的任意一个,就可以避免死锁的出现。
1) 互斥条件。即至少存在一个资源,不能被多个线程同时共享。如在哲学家问题中,一支筷子一次只能被一个哲学家使用。
2) 至少存在一个线程,它拥有一个资源,并等待获得另一个线程当前所拥有的资源。如在哲学家聚餐问题中,当发生死锁时,至少有一个哲学家拿着一支筷子,并等待取得另一个哲学家拿着的筷子。
3) 线程拥有的资源不能被强行剥夺,只能有线程资源释放。如在哲学家问题中,如果允许一个哲学家之间可以抢夺筷子,则就不会发生死锁问题。
4) 线程对资源的请求形成一个圆环。
即:线程1拥有资源1,并等待资源2,而线程2拥有资源2,并等待资源3,…,以此类推,最后线程n拥有资源n-1,并等待资源1,从而构成了一个环。这是构成死锁的一个重要条件。

如在哲学家问题中,如果规定每个哲学家必须在拿到自己左边的筷子后,才能去拿自己右边的筷子,那么讲很容易形成一个请求环,因此也就可能形成死锁。但如果我们规定其中的某一个哲学家只能在拿到自己右边筷子的前提下,才能去拿左边的筷子,那么就不会形成请求环,从而也不会出现死锁。
理解了死锁的原因,尤其是产生死锁的四个必要条件,就可以最大可能地避免、预防和解除死锁。所以,在系统设计、进程调度等方面注意如何不让这四个必要条件成立,如何确定资源的合理分配算法,避免进程永久占据系统资源。此外,也要防止线程在处于等待状态的情况下占用资源,在系统运行过程中,对线程发出的每一个系统能够满足的资源申请进行动态检查,并根据检查结果决定是否分配资源,若分配后系统可能发生死锁,则不予分配,否则予以分配 。因此,对资源的分配要给予合理的规划。下面有两种方法可以有效避免死锁。
1)有序资源分配法
这种算法资源按某种规则系统中的所有资源统一编号(例如打印机为1、磁带机为2、磁盘为3、等等),申请时必须以上升的次序。系统要求申请线程:
1、对它所必须使用的而且属于同一类的所有资源,必须一次申请完;
2、在申请不同类资源时,必须按各类设备的编号依次申请。例如:进程PA,使用资源的顺序是R1,R2; 进程PB,使用资源的顺序是R2,R1;若采用动态分配有可能形成环路条件,造成死锁。
采用有序资源分配法:R1的编号为1,R2的编号为2;
PA:申请次序应是:R1,R2。
PB:申请次序应是:R1,R2。
这样就破坏了环路条件,避免了死锁的发生。
2)银行算法
避免死锁算法中最有代表性的算法是Dijkstra E.W 于1968年提出的银行家算法:
在系统运行过程中,对线程发出的每一个系统能够满足的资源申请进行动态检查,并根据检查结果决定是否分配资源,若分配后系统可能发生死锁,则不予分配,否则予以分配。 系统安全序列的概念:对于线程序列{P1,…,Pn}是安全的话,如果对于每一个线程
Pi(1≤i≤n),它以后尚需要的资源量不超过系统当前剩余资源量与所有线程Pj(j < i )当前占有资源量之和,系统则处于安全状态(安全状态一定是没有死锁发生的)。 银行家算法的中心思想是在安全状态下系统不会进入死锁,不安全状态可能进入死锁。在进行资源分配之前,先计算分配的安全性,判断是否为安全状态。
该算法需要检查申请者对资源的最大需求量,如果系统现存的各类资源可以满足申请者的请求,就满足申请者的请求。
这样申请者就可很快完成其计算,然后释放它占用的资源,从而保证了系统中的所有进程都能完成,所以可避免死锁的发生。
死锁排除的方法
1、撤消陷于死锁的全部线程;
2、逐个撤消陷于死锁的线程,直到死锁不存在;
3、从陷于死锁的线程中逐个强迫放弃所占用的资源,直至死锁消失。
4、从另外一些线程那里强行剥夺足够数量的资源分配给死锁线程,以解除死锁状态

 

减小锁的竞争和粒度
竞争性的锁将会导致两种损失:可伸缩性和性能,所以减少锁的竞争能够改进性能和可伸缩性。
访问独占锁守护的资源是串行的——一次只能有一个线程访问它。当然,我们有很好的理由使用锁,比如避免数据过期,但是这样的安全性是用很大的代价换来的。对锁长期的竞争会限制可伸缩性。并发程序中,对可伸缩性首要的威胁是独占的资源锁。
有两个原因影响着锁的竞争性:锁被请求的频率,以及每次持有该锁的时间。如果这两者的乘积足够小,那么大多数请求锁的尝试都是非竞争的,这样竞争性的锁将不会成为可伸缩性巨大的阻碍。但是,如果这个锁的请求量很大,线程将会阻塞以等待锁;在极端的情况下,处理器将会闲置,即使仍有大量工作等着完成。
有3种方式来减少锁的竞争:

原创粉丝点击