说明
对基本的银行家算法流进行简化,梳理出关键步骤,希望可以让学习该算法的同志少走一点弯路。
算法概述
判断要不要将资源分配给当前发起请求的线程。
其实算法核心逻辑在于,借了钱给张三和李四等人,张三要借的少,李四要借的多,所以先借给张三,然后可以把张三的钱收回来再去满足李四的借款要求,再把李四的钱收回来。
规则说明
借给进程的资源必须满足它的最大需求,没达到之前无法从其身上回收它已经持有的任何资源。
案例模型
结构说明
上表中列分别对应着:进程、进程总计最多需要资源、进程已经分得、系统剩余资源。最多需要是个集合,为了简化模型,假定每个进程只需要一种资源「假定此资源为人民币,单位(元)」,固集合只有一个元素。
以张三为例:
张三,最多还需要10元。已经分到4元。系统还剩11元。
不能分配的基本原则
1⃣️如果分配完,进程拥有的超过了它所声明的最大需要,不能分配。「说了最多借五百就只能借五百,不能超,如果超出了,直接判定不借给它」
2⃣️如果分配完,让系统剩余资源变成了负数,不能分配。「把银行借空了肯定是不行的,这种情况也直接判定不能借给它」
一次银行家算法执行的主要过程
1⃣️张三发来请求{6}表示要借6元
2⃣️根据表1算出各个进程的现在最多还需要多少
3⃣️判断请求张三的请求{6}是否超出现在他的还需要{6}超出直接失败,不超出进入4
4⃣️判断请求{6}是否超出系统剩余{11},如果不超出,则进入5;如果超出说明目前还无法满足,以后可能会满足。所以进入等待。「因为系统剩余会随着其他进程的还钱而增多」
5⃣️对张三进行资源分配,分配过程即做这几件事情:
1、available -= 6「张三的请求是6元」
2、allocation[张三] += 6「张三分到6所以它的allocation要增加6元」
3、need[张三] -= 6「张三的请求满足后,它的need的对应项要减少本次请求的数量」
分配完表格内容如下:
资源分配完成了,但目前为止,只能说明借给张三是够的,但我们知道不能釜底抽薪,借给张三后很可能其他进程的请求就满足不了了,这很好理解,比如把全部家底都借给了张三,李四再找你借你咋办,拿头借?
所以下面开始的步骤,就是要判断借给张三的风险,要求借给张三不能让自己陷入无钱可借的危险之中,如果张三不满足这个条件的的话借给他的钱是要收回来的。整个步骤我们称之为「安全性算法举例」
6⃣️定义一个work集合,初始化设置为available的值。work集合是银行家算法的难点,想理解它要先理解我们现在要干嘛,我们下面的工作是要去将借给这些臭鱼烂虾的钱要回来,所以work表示的是要回来后我有多少钱,所以说work的初始值是available,表示还没去要的时候我们系统还有多少钱能用。
7⃣️扫描所有进程寻找第一个能还钱的进程,根据上文提及的规则说明可知,我们要做的就是将work的值去跟进程的need项比较,以此来判断work中的钱借给他能不能填满它的最大需求。如果能的话,就说明此进程可以还钱,然后进行步骤8。如果一个能还钱的进程都没有的话结束循环,执行10。
8⃣️处理这个能还钱的进程,主要流程为:
1、将这个进程加入安全队列「在安全队列说明他的钱可以收回来」。
2、work += 已经借给它的钱「将它的钱加给work」。
9⃣️重复7、8,知道循环结束
🔟检查安全队列数量如果等于线程数量,说明6之前的分配给张三的决定是正确的,能保证所有进程都按照安全序列中的顺序收回来,如果不等于则说明至少一个进程的钱收不回来。这时候的话就说明借给张三是不行的。要把6之前的工作撤销。
总结
银行家算法主要两个步骤。
1⃣️试分配
即按照请求,将资源试分配给符合分配条件的发起请求的进程。
2⃣️判断试分配是否会导致其他进程的钱收不回来
即重复遍历寻找钱能收回来的进程,找到了就把它加入安全队列,并把它身上的已经借到的钱收回来。最后通过判断安全队列中进程数量来知道到底能不能把所有钱收回来。
可能问题
❓安全序列到底是什么意思
安全序列{2,3,1,4,5}表示的是可以按照进程2、3、1、4、5的顺序将进程1、2、3、4、5的钱都收回来。