操作系统第五章:死锁
作者:互联网
1 思索地概念和产生原因
1.1 死锁的基本概念
1.所谓死锁,是指一组并发执行的进程彼此等待对方释放资源,而在没有得到对方占有的资源之前不释放自己占有的资源,导致彼此都不能向前推进,称该组进程发生了死锁。
2.死锁产生后,在无外力干预下,陷入死锁的各个进程都永远不能向前推进,导致这些进程不能正常结束。同时,要求共享使用死锁进程所占资源的其他进程、或者需要与死锁进行某种合作的其他进程也会受到牵连,不能正常结束。最终可能导致系统瘫痪,给系统和用户带来极大损失。因此,操作系统设计者必须对死锁现象给予充分重视。
通过上面介绍的例子可以发现,死锁具有以下特点:
① 陷入死锁的进程是系统并发进程中的一部分,且至少要有2个进程,单个进程不能形成死锁。
② 陷入死锁的进程彼此都在等待对方释放资源,形成一个循环等待链。
③ 死锁形成后,在没有外力干预下,陷入死锁的进程不能自己解除死锁,死锁进程无法正常结束。
④ 如不及时解除死锁,死锁进程占有的资源不能被其他进程所使用,导致系统中更多进程阻塞,造成资源利用率下降
1.2 产生死锁的原因
-
资源竞争
死锁产生的根本原因是资源竞争其分配不当。因为多道程序并发执行,造成多个进程在执行中所需的资源数远远大于系统能提供的资源数
计算机系统中有很多种资源,按照占用方式来分,可分为可剥夺资源与不可剥夺资源。
(1)可剥夺资源
某进程在获得这类资源后,即使该进程没有使用完,该类资源也可以被其他进程剥夺使用。例如:CPU、内存、磁盘等
(2)不可剥夺资源
当系统把这类资源分配给某进程后,不能强行收回,只能在进程使用完后自行释放,然后其他进程才能使用。这类资源众多,例如:打印机、刻录机、CD-ROM驱动器等 -
推进顺序不当
并发执行的诸进程在运行中存在异步性,彼此间相对执行速度不定,存在着多种推进顺序。并发进程间推进顺序不当时会引起死锁。
不可剥夺资源少未必一定产生死锁。死锁在一种很巧合的推进顺序中才会发生。在不能增加不可剥夺资源数量的前提下,我们要采取各种措施,尽量避免产生死锁的不合理推进顺序出现.
由以上分析我们得出以下两个结论:
(1)用户编写应用程序时或操作系统进行资源分配时应采取相应措施,避免导致死锁发生的进程间的推进顺序出现。
为避免死锁现象的产生,用户在编写应用程序时,除了考虑如何实现某种功能外,还要考虑避免死锁发生。
(2)死锁是在特定的推进顺序中才会出现,具有一定的隐蔽性。
有的死锁隐藏的很深,只有在很巧合的情况下,导致死锁的推进顺序才会发生。发生死锁的可能性远低于不发生死锁的可能性。应用程序编写者或操作系统设计者往往需要花费大量精力去测试程序或系统,才能发现死锁并解决它
2 死锁的必要条件
死锁发生必须具备一定的条件。Coffman首先提出死锁发生的4个必要条件,故又称为Coffman条件。
由于这4个条件是必要条件,一旦死锁出现,这4个条件都必然成立。因此,只要有一个必要条件被系统或用户破坏掉,就不会出现死锁现象。
四个必要条件:
(1)互斥条件
(2)请求和保持条件
(3)不剥夺条件
(4)环路等待条件
- 环路等待条件隐含着前三个条件,即只有前三个条件成立,第四个条件才会成立。
- 特别注意:环路等待条件只是死锁产生的必要条件,而不是等价定义。死锁一旦产生则死锁进程间必存在循环等待环,但存在循环等待环不一定产生死锁。这点希望读者引起注意。例如:某系统中有两个R1资源和一个R2资源。假设系统中有三个进程并发执行,存在一个环路,进程 等待 所占有资源R1,进程 等待 所占有资源R2,此时进程 占有另一个R1资源,显然进程 和进程 已陷入死锁。但是,如果进程 以后的执行过程中没有提出新的关于R1或R2的请求,且顺利执行完毕,释放其占有的资源R1给进程 ,则 和 形成的循环等待环将被打破,死锁解除。
3 死锁的处理
3.1 死锁的处理方法
(1)预防死锁
(2)避免死锁
(3)检测死锁
(4)解除死锁
3.2 资源分配图
- 资源分配图(Resource Allocation Graph)是描述死锁问题的常用工具,在很多问题的求解中都有应用。
- 资源分配图是一个有向图,该图由结对组成:G=(V,E)。式中V是顶点集,E是边集。
- 定点集V由P和R两部分构成,P={P1,P2,┄,Pn}为系统中的进程集合,R={r1,r2,┄,rm}为系统中所有资源类型的集合。边集E也由两类有向边组成,从进程Pi到资源rj的有向边记做Pi→rj,代表进程Pi提出申请一个单位的rj资源;从资源rj到进程Pi的有向边记做rj→Pi,代表一个单位的rj资源已经分配给了进程Pi。形如Pi→rj的边被称作申请边;形如rj→Pi的边被称作分配边。
- 一个进程通常用一个圆圈表示,圈内为进程的名字。一个资源类通常用一个方框表示,方框内的圆点表示系统中本类资源的个数。
4 死锁的静态预防
4.1 破坏互斥条件
-
如果允许系统中的所有资源都能共享使用,即破坏死锁的“互斥”使用条件,系统将不会发生死锁。但临界资源本身的性质决定其不能共享使用,否则无法保证正确性。
-
在实际系统中,可采用时分或空分虚拟技术把必须互斥使用的、不可剥夺的独占设备改造成为可被多个进程共享的虚拟设备,预防死锁的发生。例如采用SPOOLing技术把打印机改造成虚拟打印机,任何一个想要打印的进程将打印内容先发送到可共享的“输入井”(磁盘的一个固定区域)中,发送完毕后,该进程即认为打印完毕,而真正的打印输出到等到打印机空闲时才进行。
4.2 破坏请求和保持条件
-
破坏这个条件的办法很简单,可采用预分配资源方法。进程运行前,系统一次性地分配其运行所需的所有资源,而不是随着进程的推进而陆续分配。由于进程运行前一次性地获得了所需的所有资源,该进程可顺利执行完毕,不会发生死锁。
-
预分配资源方法在实现上还有一个很大的缺陷,即系统无法在进程执行前精确估计其所需的全部资源。因为进程是一个动态的概念,具有不确定性,即使是同一个程序,在不同的执行过程中所需要的资源也可能不同。对进程所需资源估计少了,仍会存在死锁的危险;估计多了,会造成资源浪费、进程运行延迟。
-
破坏“请求和保持”条件的另一种方法是系统在进程执行前并不把其所需的所有资源分配给它,而是边执行边申请资源。但同时规定:进程在申请新资源失败后,需要释放已经占用的所有资源。这样一来,因资源申请不成功而阻塞的进程就不再占有任何资源,死锁自然消除。此办法虽能消除死锁,但也有很大的局限性。进程使用的资源中,有的资源即使没用完也能在使用一段时间后释放,但临界资源在使用一段时间后不能随意释放。如刻录机,某进程在刻录过程中需要访问某台I/O设备,假如系统此时不能满足它的要求,于是该进程把还没使用完的刻录机资源释放后阻塞。这样一来,该进程所做的刻录工作前功尽弃,被刻录的光盘成为废盘。
4.3 破坏不剥夺条件
破坏“不剥夺”条件存在以下主要缺点:
① 系统代价较大。在剥夺用户资源时,要保存进程的上下文现场,在进程重新获得资源时,要恢复进程上下文现场,系统开销较大,程序执行延迟。
② 临界资源不可以剥夺。如果强行剥夺,会产生不良后果。
4.4 破坏环路等待条件
环路等待出现的根本原因是并发执行进程请求资源的顺序是随机的。假如有两个进程,一个进程先申请资源A再申请资源B,另一个进程先申请资源B再申请资源A。这两个进程随机推进时,就可能产生死锁。如果系统事先把全部资源按类型进行线性排队,并对每类资源赋予不同的序号,然后按序进行分配,规定进程不能连续两次申请同类资源。这样一来,进程在申请、占用资源时就不会形成资源申请环路,也就不会发生环路等待。
- 此方法存在着不足。
- 比如,用户在编程时要牢记系统中所有资源的编号,严格按照资源的编号申请资源,增加了用户编程负担。如需要在申请大序号资源后申请小序号资源,必须修改程序先申请小序号资源,然后再申请大序号资源。提前申请小序号资源会导致小序号资源闲置时间过长,降低资源利用率和系统并发程度。
- 此外,给系统中所有资源合理的编号也非易事。资源编号一旦确定就须相对稳定,这在某种程度上限制了新类型资源的增加。
5 死锁的静态避免
5.1 系统的安全状态
- 所谓安全状态是指操作系统能够按照某种进程执行序列,如<P 1, P2, …,Pn>,为进程分配所需资源,使得每个进程都能执行完毕,此时我们称系统处于系统安全状态。进程执行序列<P1, P2, …,Pn>为当前系统的一个安全序列。如果操作系统无法找到这样一个安全序列,则称当前系统处于不安全状态。
- 系统安全状态与死锁避免有很大关系。
- 由安全状态定义可知,处于安全状态的系统不会产生死锁。即使某个进程 所需的资源总数超过系统当前可用空闲的资源总数, 可以等待其他进程执行完毕后释放资源,系统把释放的资源分配给进程 , 最终能获得所需的全部资源,从而执行完毕。
- 处于不安全状态的系统一定会形成死锁吗?
并非所有的不安全状态都会导致死锁状态。但当系统进入不安全状态时,便有了导致死锁状态的可能。如果能保证每次资源分配后,系统都处于安全状态,则不会发生死锁。
5.2 银行家算法
银行家算法的基本思想是:在资源分配前,资源分配程序计算资源分配后系统是否处于安全状态,如处于安全状态则把资源分配给申请进程,如处于不安全状态则令申请资源的进程阻塞,不响应其资源申请。
银行家算法的核心理念是把资源分配给那些最容易执行完成的进程,保证系统中各个进程最终都能正常完成。
银行家算法的本质是死锁的避免,由于它并没有破坏产生死锁的4个必要条件之一,不属于死锁预防。
6 死锁的检测和死锁
6.1 等待图检测死锁
6.2 多体资源类死锁检测算法
6.3 死锁解除方法
当死锁发生并被检测出来后,必须采取相应措施解除死锁。一种可能的方法是通知系统管理员进行人工干预,另一种方法是操作系统自动解除死锁并在适当时机恢复相应进程运行。
具体来说,主要有以下三种方式 :
(1)剥夺资源恢复
(2)进程退回
(3)撤销进程
6.4 鸵鸟算法
- 据说鸵鸟看到危险动物时就把头埋在沙砾中,装作看不到。当人们对某一件事情没有一个很好的解决方法时,或者解决问题的方法代价太大而得不偿失时,人们就借鉴鸵鸟的办法,忽略问题的存在。
- 在死锁问题上,鸵鸟算法就是不对死锁采取任何处理方法。著名的UNIX、Linux和Windows操作系统在分析了死锁发生的频率、系统因各种原因崩溃的频率、死锁的严重程度以及解决死锁问题的代价之后都采用了鸵鸟算法。
- 采用鸵鸟算法的代价就是用户必须忍受死锁带来的诸多不便。
- 但实际上,经过大量统计,死锁发生的概率是很小的,只有在极偶然的情况下才会出现死锁。
- 鸵鸟算法也是操作系统设计者处理死锁问题的一种不错选择。
7 线程死锁
在支持多线程的操作系统中.除了会发生进程之间的死锁外,还会发生线程之间的死锁。由于不同的线程可以属于同一进程,也可属于不同的进程。因此,与进程死锁比较,线程死锁分为属于同一进程的线程死锁和属于不同进程的线程死锁。
(1)同一进程的线程死锁
线程的同步工具有互斥锁。由于同一进程的线程共享该进程资源,为了实现线程对进程内变量的同步访问,可以采用互斥锁。
(2)不同进程的线程死锁
如果在进程P1内存在一组线程{P11,P12,…,P1m},在进程P2内存在一组线程{P21,P22,…,P2n}。同一时间段内,进程P1内的线程获得资源R1,进程P2内的线程获得资源R2。之后,进程P1内的某个线程P1i请求资源R2,由于不能满足而进入阻塞状态;进程P2内的某个线程P2j请求资源R1,由于不能满足也进入阻塞状态。线程P1i和线程P2j相互等待对方释放资源,这时出现了不同进程线程间的死锁。
标签:操作系统,系统,死锁,第五章,线程,进程,资源,资源分配 来源: https://blog.csdn.net/weixin_42260102/article/details/100569315