注意区分两个概念
死锁(Deadlock):指进程之间无休止地相互等待
饥饿(Starvation):指一个进程无休止地等待
在多道程序系统中,虽然可借助于多个程序的并发执行来改善系统的资源利用率,提高系统吞吐量,但可能引发死锁(因为上面也提到了死锁是进程间无休止地相互等待)
进一步分析:
死锁是指多个进程在运行过程中因争夺资源而造成的一种僵局,当程序处于这种状态时,若无外力作用,他们都将无法再向前推进,因此可以看出:关于死锁,根本不存在完美、圆满的解决方案。
饥饿与饿死反映了资源分配策略的不公平性,死锁是因为进程竞争资源,但系统拥有的数量有限,或并发进程推进的顺序不当而造成的一种永远等待资源的僵局。而饥饿是指每个资源占用者都在有限时间内释放占用资源,但申请进程仍然长时间得不到资源的现象。
综上所述:产生饥饿并不一定意味着一定产生死锁
【实例】
死锁产生的原因:双方都拥有部分资源,同时在申请对方已占有的资源。
因此产生死锁的原因为:
- 竞争资源。例如系统中供多个进程共享的资源
- 进程间推进顺序非法。进程在运行过程中,请求和释放资源的顺序不当,同样会导致死锁
系统中的资源可分为两类:
··可剥夺和非剥夺性资源
可剥夺性资源:分配给进程后可以被高优先级的进程剥夺。如CPU和主存。
不可剥夺性资源:分配给进程后只能在进程用完后释放。如磁带机、打印机等。
··永久性资源和临时性资源
永久性:打印机。可顺序重复使用
临时性:进程产生被其他进程短暂使用的资源,如数据资源:“生产者/消费者”算法中的信号量。它可能引起死锁。
补充所有的硬件资源及部分软件资源属于永久资源;而部分软件资源(如:信号量、中断信号及交互作用时产生的信息等)属于临时性/消耗性资源。
进程推进顺序对死锁的影响
分析:
若并发进程P1和P2按曲线④所示的顺序推进,它们将进入不安全区D内。此时P1保持了资源R1, P2保持了资源R2, 系统处于不安全状态。因为,这时两进程再向前推进,便可能发生死锁。例如,当P1运行到P1:Request(R2)时,将因R2已被P2占用而阻塞;当P2运行到P2: Request(R1)时,也将因R1已被P1占用而阻塞,于是发生了进程死锁。
产生死锁的四个必要条件:(四个条件都具备就会死锁,缺一不可)
- 互斥条件:进程对所分配到的资源进行排他性使用
- 请求和保持条件:进程已经保持了至少一个资源,又提出新的资源请求,而新的资源请求又被其他进程占有只能造成自身进程被阻塞,但对自己获得的其他资源保持不放,必然影响其他进程。
- 不剥夺条件:进程已获得的资源未使用完之前不能被剥夺,只能在使用完时有自己释放。
- 环路等待条件(指在发生死锁时,必然存在一个进程资源的环形链,即进程集合{P0,P1,P2,···,Pn}中的P0正在等待一个P1占用的资源;P1正在等待P2占用的资源,,Pn正在等待已被P0占用的资源)
事先预防
1.预防死锁:设置限制条件,破坏四个必要条件(较容易实现,限制条件的严格也会降低自愿利用率和吞吐量)
2.避免死锁:用某种方法防止系统进入不安全状态(实现上有一定难度,但可获得较高吞吐量)
事后处理
1.检测死锁。
2.解除死锁:
与检测死锁配套使用
常用的方法:撤销或挂起一些进程,回收部分资源分配给已阻塞的进程
预防死锁的方法
资源的排他性无法更改,需要在其他三个条件上入手
1.破坏“请求保持条件”:所有进程开始运行之前,必须一次性申请所需的全部资源(AND信号量集)—算法简单、易于实现、安全。但缺点是资源浪费严重、进程会延迟运行。
2.破坏“不剥夺条件”:允许进程先运行,当提出的新的要求不被满足时必须释放它自己保持的全部资源,以后需要时再次重新申请,----实现起来较为复杂且代价大,可能出现反复申请和释放等情况。
3.破坏“环路等待条件”:有序设置资源,将所有资源按类型进行线性排队,赋予不同序号,所有进程必须严格按照序号进行资源请求。----与前两种相比资源利用率和吞吐量明显改善,但是资源编号限制新设备的增加,应用中的使用设备顺序与规定的顺序并不协调,限制了用户编程自由。p20