要想说银行家,首先得说死锁问题,因为银行家算法就是为了死锁避免提出的。
问什么叫做银行家算法呢?因为这套算法适用于银行贷款业务,适用于银行家的决策。
一个银行家共有20亿财产
第一个开发商:已贷款15亿,资金紧张还需3亿。
第二个开发商:已贷款5亿,运转良好能收回。
第三个开发商:欲贷款18亿
银行家是资源,开发商是进程。在操作系统中,有内存,硬盘等等资源被众多进程渴求着,那么这些资源怎么分配给他们才能避免“破(si)产(suo)”的风险?
我还是从头讲起,这样也能复习以前的的知识点。
首先,为什么会产生死锁,产生死锁的必要条件是什么?
(1)互斥:至少有一个资源必须处于非共享模式,即一次只能有一个进程使用。如果另一进程申请该资源,那么申请进程必须等到该资源被释放为止。
(2)占有并等待:一个进程必须占有至少一个资源,并等待另一资源,而该资源被其他进程所占有。
(3)非抢占:资源不能被抢占,即资源只能在进程完成任务释放后,才能被其他进程占有。
(4)循环等待:有一组等待进程{P0,P1,···,Pn},P0等待的资源为P1所占有,P1等待的资源为P2所占有,…,Pn-1等待的资源为Pn所占有,Pn等待的资源为P0所占有。
注:强调所有4个条件必须同时满足才会出现死锁。循环等待意味着占有并等待,这样四个条件并不完全独立。
资源分配图描述:
如果分配图没有环,那么系统就没有进程死锁,如果分配图有环,那么可能存在死锁。
图一存在死锁, 图二存在环但没有死锁。
死锁预防
出现死锁要满足4个必要条件,只要确保一个必要条件不成立,就能预防死锁发生。下面通过讨论这4个必要条件来研究死锁预防方法。
- 互斥:共享资源不是必须的,而非共享资源必须保持互斥
- 占有并等待:必须保证进程申请资源的时候没有占有其他资源;要求进程在执行前一次申请全部的资源,只有没有占有资源时才可以分配资源;利用率低,可能出现饥饿
- 非抢占:如果一个进程的申请没有实现,它要释放所有占有的资源
- 循环等待:将所有的资源类型放入资源列表中,并且要求进程按照资源表中递增的顺序申请资源
为了实现银行家算法,必须要有几个数据结构:
注:设n为系统进程的个数,m为在资源类型的种类。
Available:长度为m的向量。表示每种资源的现有实例的数量。
Max:n * m矩阵。定义每种进程的最大需求。
Allocation:n * m矩阵。定义每个进程现在所分配的各种资源类型的实例数量。
Need:n * m矩阵。表示每个进程还需要的剩余的资源。
定义如下的数据结构:
int n,m; //系统中进程总数n和资源种类总数m
int Available[1..m]; //资源当前可用总量
int Allocation[1..n,1..m]; //当前给分配给每个进程的各种资源数量
int Need[1..n,1..m];//当前每个进程还需分配的各种资源数量
int Work[1..m]; //当前可分配的资源
bool Finish[1..n]; //进程是否结束
安全判定算法
- 1.初始化
Work = Available(动态记录当前剩余资源)
Finish[i] = false(设定所有进程均未完成)
- 2.查找可执行进程Pi(未完成但目前剩余资源可满足其需要,这样的进程是能够完成的)
Finish[i] = false
Need[i] <= Work
如果没有这样的进程Pi,则跳转到第4步
- 3.(若有则)Pi一定能完成,并归还其占用的资源,即:
Finish[i] = true
Work = Work +Allocation[i]
GOTO 第2步,继续查找
- 4.如果所有进程Pi都是能完成的,
即Finish[i]=ture
则系统处于安全状态,否则系统处于不安全状态
举栗子
考虑这样一个系统,有5个进程P0~P4,3种资源类型A、B、C。资源类型A有10个实例,资源类型B有5个实例,资源类型C有7个实例。假定在时刻T0,系统状态如下:
- | Allocation | Max | Avaliable |
---|---|---|---|
A B C | A B C | A B C | |
P0 | 0 1 0 | 7 5 3 | 3 3 2 |
P1 | 2 0 0 | 3 2 2 | |
P2 | 3 0 2 | 9 0 2 | |
P3 | 2 1 1 | 2 2 2 | |
P4 | 0 0 2 | 4 3 3 |
矩阵Need的内容定义成Max-Allocation:
- | Need |
---|---|
A B C | |
P0 | 7 4 3 |
P1 | 1 2 2 |
P2 | 6 0 0 |
P3 | 0 1 1 |
P4 | 4 3 1 |
可认为系统现在处于安全状态,因为存在一个安全序列 P1,P3,P4,P2,P0 。
现在假定进程P1再请求1个A类资源和两个C类资源,这样Request1 = (1,0,2)。为了确定这个请求是否可以立即允许,首先检测Request1 <= Available(即,(1,0,2) <= (3,3,2)),其值为真。接着假定这个请求被满足,会产生如下新状态:
- | Allocation | Need | Avaliable |
---|---|---|---|
A B C | A B C | A B C | |
P0 | 0 1 0 | 7 4 3 | 2 3 0 |
P1 | 3 0 2 | 0 2 0 | |
P2 | 3 0 2 | 6 0 0 | |
P3 | 2 1 1 | 0 1 1 | |
P4 | 0 0 2 | 4 3 1 |
必须确定这个状态是否安全。为此,执行安全算法,并找到顺序 P1,P3,P4,P0,P2 满足安全要求。因此,可以立即允许进程P1的这个请求。
然而,可以发现当系统处于这一状态时,是不能允许P4的请求(3,3,0)的,因为没有那么多资源可用。也不能允许P0的请求(0,2,0);虽然有资源可用,但是这会导致系统处于不安全状态。