下面我们来讨论死锁的处理方法
死锁的处理方法呢
我们通常情况下可以理解为
跟我们的消防的方法是很类似的
这里头呢 我们基本上可以按照
消防的那些处理方法来进行类比
首先第一个 就是死锁预防
确保系统永远不会进入死锁状态
比如说我们在消防里头
为了避免火灾
我在一些敏感的区域里头
我就会限定 在这个区域里头
不允许用任何的火
好 那这样一来的话
在这个区域里出现火灾的
可能性也就没有了
那对于死锁来说呢
我们也是一样的
我们在那里呢
死锁可能出现的时候
有四个必要条件
那我们把那四个必要条件里的
任何一个去掉
它就不会进入死锁了
但是这时候呢
实际上它的问题是说
你不让它使用这些资源
不让那四个条件得到满足
那这时候呢 实际上可能的问题是
系统的资源利用效率比较低
那这就是第二种做法
就是死锁避免
这可以理解为
我们采用严格的监管措施
到底是否是允许用火
有一个严格的审批流程
比如说在某些区域里头
你不可以完全禁止用火
那这时候呢 我就会说
什么样的人 有什么样的资质的人
能够处理这个问题的人 你可以用
比如说在林区的防火
只有相应的 有资质的人
你可以在这里头去使用
这是我们这里的第二种做法
在使用之前进行判断
只允许不会出现死锁的进程请求资源
这就是我们在这里头 死锁避免
再有一种做法呢
是我在管理不过来的时候
那我就会允许第三种做法
死锁检测和恢复
是否会出现死锁
这个事我管不过来
那我也就不管了
比如说像在居民用火
你不允许他不用火是不可能的
你进行严格的监管呢也做不到
那这怎么办呢
我们就预备一个消防队
出了问题之后我派消防队去
那么这也是一样的
我检测到系统进入死锁状态后
那我就进行恢复
而在我们这几种做法里头呢
在我们实际的操作系统里呢
通常情况下我们把这件事情
指派给应用进程来处理
通常操作系统是忽略死锁的存在
这是我们目前
大多数操作系统的做法
那有了这样一个非常粗的介绍之后
我们下边就来具体看一下
这三种做法里的情况
第一个 死锁预防
也就是说
我们限制进程申请资源的方式
那怎么来限制呢
就是限制的结果是
不满足死锁的必要条件
怎么能做到不满足死锁的必要条件呢
我们有四个条件
任何一个不满足就可以了
比如说第一个互斥
我们把需要互斥访问的资源
封装成可以同时访问的
那这件事情就没了
一个实际的例子是说我们的打印机
在早期的时候 打印机每个进程
可以往打印机上送打印作业
那这时候 在送的过程当中呢
是必须互斥的
如果说两个进程同时往一台打印机上
送打印作业
那这时候打出来的结果
是谁也不能用了
而现在呢 我们在使用打印机的时候
你基本上感觉不到这一条
原因在于 我们在打印机里加了缓冲
只有当前一个送完了之后
它才会去接收另一个的打印请求
那这就是我们现在的
网络打印机的做法
好 那这样一来的话
它就可以大家一起使用
只是说在打印机内部
它给你协调谁先谁后
这是第一个 把互斥条件去掉
第二个是说 我把持有并等待
这个条件给去掉
那在这个条件里头呢
实际上是我申请到的一部分资源
我再去申请另一部分资源
那我怎么可以把它去掉呢
一种做法是说你在请求资源的时候
你不能占用任何资源
这指什么意思呢
这指是说你要想申请资源的话
你就必须一次
把所有的资源全部申请到
如果说你已经申请了一部分
然后再去申请的话
那就会出现死锁的可能性
这个呢 有一个形象的比喻是说
我们在贷款的时候
你希望去做一个项目
好 这时候呢
需要银行给你贷款
那你可以说 我一次把所有
我需要的钱全部贷出来
这样就避免一种情况是说
我做到一半 我钱不够用了
这种情况
但是这时候呢 它的问题是
它的资源效率会是利用比较低的
这种做法更细化下去的一种
可以操作的做法就是
我进程在开始的时候
申请所有需要的资源
如果说我不满足
我这个申请的要求的话
那就不允许它开始
那这样一来每一个开始进程
它就确信它一定能执行到结束
这样的话我这个问题也解决掉了
这是它最主要的问题
资源利用效率太低
你比如说像我们修一个水电站
持续几年 十几年的时间
那你最开始的时候
一口气把它需要的资金全部到位
那这时候实际上
它的利用效率是非常低的
那第三个做法呢 是非抢占
我们在前边说有一个条件
你分配资源之后
进程不主动放弃的话
我是没有办法回收的
这样的话 我才能构成
循环无限期等待
如果说在这里头加一个条件
一旦你申请的资源不能立即分配
你就释放你已经占用的所有资源
如果说我们有这一条的话
那这件事情也没有了
这个对于我们刚才说的
单向通行桥梁的情况
就是一旦两辆车撞上了
那这时候两辆车都会往回倒
那再来申请的时候
这个单向通行的桥梁呢
也就能通行了
只有在这里头 进程能够获取到
它所有需要的资源
它才给它分配
这样的话实际上某种角度上
跟我们前面说的
去掉持有并等待这个条件的做法
有类似的地方
也相当于在那里头呢
我是要申请一次全部申请
在这地方呢 我申请
在我再申请的时候
我必须需要的资源都有
我才能够往下申请
最后一个 循环等待
我们怎么把它去掉呢
实际上就是对资源排序
按照我们固定的顺序来申请资源
这时候我就不存在循环等待了
这时候它会有啥问题呢
和我们前边的做法有类似的地方
按照顺序来申请
可能你先申请的某一项资源
实际上我是后用到
这时候也会有效率下降的问题
这是我们说到的死锁预防
通过这一类办法呢
我们可以避免死锁出现的四个条件
任何一个不成立 那这事就没了
第二类做法呢 是死锁避免
这是针对第一类做法
如果说我想完全禁止掉
它出现死锁的话
那这时候呢 我的资源利用效率低
那提高资源利用效率的办法呢
就是给我自己分配资源的时候
把这个手续变得更复杂
那这里做法就是
我利用额外的先验信息
在分配资源的时候
我来判断是否会出现死锁
如果说有可能出现死锁
那我就不分配给你
那只是没有可能出现死锁的情况
我才分配给你
这就是我们这里说的死锁避免
这就有点像在银行里 你去借款
它依据你的信用情况
来判断我借给你之后
你是否会如期归还
如果说我判断完的结果
你是有可能不如期归还
当然我判断完之后
你有可能不如期归还
你也有可能是能归还的
好 我判断完了之后
只是信用比较好的
我才分配给它资源
当然这种情况它也是有风险的
那在计算机系统里头呢
就是你对先验知识的准确性了
具体做法是这样的
要求进程事先声明你的需求量
也就是说你最大的需求资源数是多少
银行里头可以满足这个资源数
那我就把这资源分配给你
那这时候呢 实际上相当于
我限定提供和分配资源的时候
我必须能确保满足进程的最大需求
如果不能满足的话
我就是会有麻烦的 会出现死锁
那我就不分配给你
那这时候说 我们怎么知道
它是否会有麻烦呢
那这时候就是 我们动态进行检查
那这时候就是我们前面说到的
资源分配图 在这就能用得上了
我判断分配给你这个资源之后
不会出现死锁
我就把它分配给你
这是第二种做法
那在这第二种做法里头呢
就有一个比较麻烦的事
银行或者说系统必须来动态地判断
我是否分配给你资源之后
不会出现死锁
那这就是我们这里说到的
系统资源分配安全状态
你在请求的时候系统判断是否安全
安全了我才分配给你
那怎么算是安全呢
实际上就是针对
所有进程已占用的资源
我来找出一个进程的执行序列
这个序列执行
保证我已有的资源能够满足
这个序列执行到结束
如果能行的话
我这系统的状态就是安全的
好 你要求分配的资源
我就是可以分配给你了
稍微具体一点是这样的
我当前所有占用资源的进程
P1到Pn
我在这里给它做一个排序
这个排序有这样一个要求
Pi要求的资源
它小于我当前可用的空闲资源
和Pj已经占用的资源
这个Pj是在这个序列当中
小于i的所有之间
也就是说在它之前的
这些进程已经占用的资源
加上现在可用的这些空闲的资源
它俩搁在一起
是否能满足进程PI的要求
如果能满足
对于所有这些都能满足的话
那这就是安全的
这就相当于是什么样的做法呢
就是第一个进程Pi
它没有再往前的进程了
所以这时候呢
当前可用的资源
必须能够满足P1的需求
那这时候它就是安全的
如果说后续的某一个Pi
它请求的时候
当前可用的不够
前边还有一些被其他进程占用了
那这时候它就等待
等待你前边的这些进程执行结束
那你的占用资源不就回来了吗
由于有上边的一条回来的资源
就能够满足我的要求了
搁在一起我就可以执行完毕了
执行完之后
我这事就行了
等到整个序列当中的
任何一个进程都执行结束
最后一个也就能满足它的需求
到这我们整个系统里的
占有资源的进程都能正常的完成
那我的系统就是安全的
有了这个描述之后
我们的安全和死锁之间的关系呢
就可以用这个图来表示
说我们在这个系统里头
处于安全状态的
它一定不会出现死锁
那是不是说我不安全的
就一定会死锁呢
也不是这样的
就好比说银行
我把这个款贷出去
有可能对方还不了我
但是他也有可能能还我
如果他能还的话
这件事情也是可做的
这就看你的风险有多大了
实际上我们在这画了一个更大的圈
用不安全其中包括死锁状态
我只是对于安全情况我来分配资源
这样的话
从而保证我系统不会出现死锁
如果说不安全
是有可能出现死锁的
我们避免出现死锁
我就在这画的这条线上
来保证我系统是处于安全的状态
到这我们说清楚了
死锁的处理的三类办法
基本上是按照我们消防的
那三类办法来做处理