1. 概述
死锁就是进入了一个,问题无法解决的困境。就像在路上开车,两辆车卡在一起,谁都不出来,谁都走不动。每辆车必须让对方先出来自己才能出来,这就卡住了。像古代建筑的榫卯结构一样。
1.1 资源问题
发生死锁很大一个可能是资源不足。有些资源是有限的,有些资源是不可抢占的。
计算机系统中产生死锁,可能会由于竞争不可抢占资源而陷入僵局。每个人都要接入这个文件。当两个进程都尝试接入这个资源有可能导致状态出错,大家都打不开。
1.2 死锁
产生死锁有几个必要条件
1)互斥条件:进程分配到的资源的使用是独占性的,排他的。
2)请求和保持:进程至少已经拥有了一个资源(保持),但是不够,还要更多资源(请求),此时新的资源被其他进程所保持,而该进程正在请求目前进程所保持的资源。
3)不可抢占:进程拥有的资源不可被抢占,只能进程自己释放。
4)循环等待:发生死锁后,必然是进程间的循环链。
因此,目前处理死锁的方法大致归类四种。包括预防死锁和避免死锁,检测死锁,以及解除死锁。
其中预防死锁和避免死锁最大的区别是,预防死锁是通过破坏死锁产生的条件,尽量预防死锁的产生。避免死锁是在分配资源的时候就已经考虑到不会出现死锁,才会给进程分配资源。
2. 预防死锁
2.1 破坏请求和保持条件
要破坏这个条件,首先要保证,当一个进程在请求资源的时候,它不能占用不可抢占资源,可以通过以下两个方法实现。
第一种协议:所有进程在开始运行之前,必须一次性申请它在运行过程中所需要的全部资源,这样进程在运行过程中就不会再提出资源申请,就不会出现请求和保持的情况。但是这个方法弊端也很多,一个进程的所有资源不是在他运行的任何时刻都在使用的,会造成资源的大量浪费。其次也可能导致进程饥饿。倘若某些资源长期被其他进程占用,该进程可能很久才开始执行。
这个协议破坏了请求出现的可能。
第二种协议:这是对第一种协议的改进,进程只需要先获取运行初期所需要的资源然后就开始运行,然后在运行过程中不断释放已经使用完的资源。由于在运行过程中不断释放资源,它破坏了保持出现的可能。
2.2 破坏不可抢占条件
如果要破坏不可抢占条件。可以让当进程占用不可抢占条件的时候,又申请新的资源失败,则需要释放不可抢占资源。但是这个方法有很大弊端,像打印机这一类,如果把资源释放了,可能导致一些前期工作无效。
3. 避免死锁
避免死锁是在为进程分配资源的时候就要判断,分配完资源后,进程会不会进入不安全的状态,以之来判断是否分配资源。
3.1 系统安全状态
要避免死锁则需要判断系统安全状态,如何判断安全状态?安全是什么状态?
所谓安全状态就是,在进程推进顺序中,系统能为每个进程都分配好所需的资源,达到资源的最大利用率。系统必须保证按照某个顺序,,能让每个进程都能够顺序运行(称为安全序列),否则为不安全状态。
如下图看一个例子。
在此时系统仍然是安全的,因为此时的安全序列是P2 P1 P3。
但是倘若P3又申请多了一个进程,则会变成不安全状态,因为找不到一个合适的序列。
3.2 银行家算法
避免死锁最有代表性的算法就是银行家算法。就是对每个“借钱”出去的人,判断一下这个人是否安全,安全才“借钱”出去。
3.2.1 算法数据结构
1)可利用的资源数组Available。表示每一类资源可利用的数量
2)最大需求矩阵MAX。n个进程中对m类资源的需求
3)分配矩阵Allocation。n个进程已经分配的m类资源。
4)需求矩阵Need。每个进程尚需的资源量。
3.2.2 算法实现
request(i)是进程P(i)的请求数组,如果request(i)=K,即表示进程P(i)需要K个资源。当进程P(i)发出资源请求后,做如下步骤
1)如果request(i) <= need[i, j],就进入步骤二,反之,就认为是出错了,因为进程申请的资源大于原先宣布需要的资源。
2)如果request(i) <= available[i],就进入步骤三,反之表示需要的资源比现有资源少。
3)系统试探性分配资源,并修改数值。
4)系统测试查看分配后的进程序列是否安全,不安全则回退。
3.2.3 安全性算法
安全性算法怎么实现?其实原理也很简单,就是不断遍历找到一个后面满足要求的进程,倘若无法最后实现全部进程完成,则进入不安全状态。