一句话速通银行家算法:
try 分配资源, if safe() then continue;
else 归还资源 并且 sleep(当前任务).
好,本文结束。
hh其实并没有,接下来我将解释这句话以及银行家算法究竟是个啥。
ps: 银行家算法是try assign(), 而还有个锁的api是trylock(),大家可以类比着看一下。
银行家算法:
- 设计目标:
利用内核调度解决(预防)死锁问题.
- 重要前提:
假设知晓所有任务及它们所需的全部资源.
- 缺陷:
a) 上述假设基本上很难达成,仅在某些特殊场景下适用,如嵌入式开发;
b) 银行家算法限制了并发程度,有些任务必须等到足够资源时才能运行。
- 算法思路(以进程为例):
参数说明:
Available[m] : 系统中可用资源数组,有m种资源;
Max_Need[i][j]:进程i对第j种资源的最大需求数量, 这是个常数数组,是我们假设已经得到的;
Allocated[i][j]:进程i已被分配第j种资源的数量;
mayNeedmoreMax[i][j]:进程i对第j种资源最多还需要多少个,由计算得到,(mayNeedmoreMax[i][j] = Max_Need[i][j] -- Allocated[i][j]);
算法主体(tryAssign, and check safety):
当进程i申请资源时(request[m])
1) 判断是否 ∀ j 满足 request[j] <= mayNeedmoreMax[i][j],含义是"当前需求值"不能超过"最大可能需求值", 为什么可以看step3;
2) 判断是否 ∀ j 满足request[j] <= Available[j], 含义是"当前需求"是否可以被满足, 至于为什么也可以看step3;
2.5) 若以上两个判断均通过, 则进入step3; 否则sleep当前进程;
3) try assign, 尝试分配资源:
i) Available := Available -- request; (数组减法, 简略写)
ii) mayNeedmoreMax := mayNeedmoreMax -- request;
iii) Allocated := Allocated + request;
在step3中, 我们进行了两次数组的减法, 为了确保结果非负, 我们必须进行step1与step2的两次判断;
4) 判断step3中的try assign是否可行/无死锁/安全,isSafe()?
4.1) 若isSafe判断通过, 则try assign成立, 就这么分配资源就行;
4.2) 否则归还系统资源 (别忘了归还,相当于回滚状态),并sleep 当前进程。
下面进一步说明step4中的安全性/可行性判断函数isSafe():【本函数里发生的都是假想的,并没有真正地分配或回收资源,只是一种可行性验证】
isSafe() {
- 初始化:
Work[m] := Available[m], 新建Available数组的副本
Finished[n] := {False}, n个进程全部标记为未完成, 或者其他情况
- 找到一个( (!Finished[i]) && (∀j|mayNeedmoreMax[i][j]<=Work[j]) )的进程i, 翻译成人话就是:找到一个(未完成的)且(最大所需资源数小于可用资源的)进程;
2.1) 若能找到, 则执行step3; 否则, 执行step4
- (我们(假装)执行完了选中的进程i, 并取回其资源)
Work := Work + Allocated[i][], 取回进程i占有的资源,
Finished[i] = true, 进程i(假设)执行完成,
执行step2; (循环step2 与 step3)
- 如果Finished[]中全是true, 则安全性/可行性检查通过; 否则不通过。
其实银行家算法挺麻烦的, 而且据说不常用, 所以大概只要掌握到开篇那句tryAssign的程度, 理解算法核心思想就差不多了吧...