一 、 死锁的感念
同一个线程先后两次调用lock,在第一次调用时,由于锁已经被占,该线程会挂起等待别的线程释放锁,然而锁正是被自己占着的,该线程又被挂起,没有机会释放锁,因此,就永远处于挂起等待状态了,这就叫做死锁。
二、产生死锁的原因
(1).竞争资源。当系统中供多个线程共享的资源如打印机,公用队列等,其数目不足以满足诸线程的需要的时候,会引起诸线程对
资源的竞争而产生死锁。
(2).线程间推进顺序非法。线程在运行过程中,请求和释放资源的顺序不当,也同样会导致产生线程死锁。
三、产生死锁的条件
(1).互斥条件:指线程对所分配的资源进行排它性使用,即在一段时间内某资源只由一个线程占用。如果此时还有其它线程请求该
资源,则请求者只能等待,直至占有该资源的线程用毕释放。
(2).请求和保持条件:指线程已经保持了至少一个资源,但又提出了新的资源请求,而该资源又被其它线程占有,或者已经拥有了
该资源却又再次请求,此时请求线程阻塞,但又对自己已获得的资源保持不放。
(3).不剥夺条件:指线程在已获得的资源,在未使用完之前,不能被剥夺,只能在使用完时由自己释放。
(4).环路等待条件:指在发生死锁时,必然存在一个线程--资源的环形链,即线程集合{P0,P1,P2,P3,...Pn}中的P0正在等待P1占用
的资源;P1正在等待P2占用的资源,......,Pn正在等待已被P0占用的资源。
四、处理死锁的方法
(1).预防死锁。这是一种较简单和直观的方法。该方法是通过设置某些限制条件,去破坏产生死锁的四个必要条件中的一个或几个
,来预防发生死锁。但由于所施加的限制条件往往太严格,因而会导致系统资源利用率和系统吞吐量低。
(2).避免死锁。该方法同样是属于事先预防的策略,但它并不须事先采取各种限制措施去破坏产生死锁的四个必要条件,而是在资
源的动态分配过程中,用某种方法去防止系统进入不安全状态,从而避免发生死锁。这种方法只需事先施加较弱的限制条件,便可
获得较高的资源利用率及系统吞吐量,但在事实上有一定的难度。目前在较完善的系统中常用此方法来避免发生死锁。
(3).检测死锁。这种方法并不须事先采取任何限制性措施,也不必检查系统是否已经进入不安全区,而是允许系统在运行过程中发
生死锁。但可通过系统所设置的检测机构,及时的检测出死锁的发生,并精确地确定与死锁有关的线程和资源;然后采取适当措施
,从系统中将已发生的死锁清除掉。
(4).解除死锁。这是与检测死锁相配套的一种措施。当检测到系统中已发生死锁时,须将线程从死锁状态中解脱出来。常用的实施
方法是撤销或挂起一些线程,以便回收一些资源,再将这些资源分配给已处于阻塞状态的线程,是之转为就绪状态,以继续运行。
死锁的检测和解除措施有可能使系统获得较好的资源利用率和吞吐量,但在实现上难度也最大。
五、银行家算法
避免死锁算法中最有代表性的算法是Dijkstra E.W 于1968年提出的 银行家算法 :银行家算法是避免死锁的一种重要方法,防止死锁的机构只能确保上述四个条件之一不出现,则系统就不会发生死锁。通过这个
算法可以用来解决生活中的实际问题,如银行贷款等。
程序实现思路银行家算法顾名思义是来源于银行的借贷业务,一定数量的本金要应多个客户的借贷周转,为了防止银行家资金无
法周转而倒闭,对每一笔贷款,必须考察其是否能限期归还。在操作系统中研究资源分配策略时也有类似问题,系统中有限资源
要供多个进程使用,必须保证得到的资源的进程能在有限的时间内归还资源,以供其他进程使用资源。如果资源分配不得到就会发
生进程循环等待资源,则进程都无法继续执行下去的死锁现象。
把一个进程需要和已占有资源的情况记录在进程控制中,假定进程控制块PCB其中“状态”有就绪态、等待态和完成态。当进程在处于等待态时,表示系统不能满足该进程当前的资源申请。“资源需求总量”表示进程在整个执行过程中总共要申请的资源量。显然,每个进程的资源需求总量不能超过系统拥有的资源总数, 银行家算法进行资源分配可以避免死锁。这是讲述进程中死锁的现象,在线程中同样适用。