避免死锁问题---银行家算法
算法背景:为实现银行家算法,在每一个新进程进入系统时,它必须申明在运行过程中,可能需要的资源类型的最大单元数目,其数目不应超过系统所拥有的资源总量。当进程请求一组资源时,系统必须先确定是否拥有足够的资源分配给该进程。如果有,再进一步将这些资源分配给进程后,再检查该系统是否处于不安全状态,如果不会,再将资源真正分配给它,否则,就让进程等待。
算法原理:
1.银行家算法中的数据结构
1.1 可利用资源向量Avaliable。这是一个含有m个元素的数组,其中每一个元素代表一类可利用的资源数目,其初始值为系统中所拥有的该类资源的数目,其数值随着该资源分配和回收的行为而动态的改变。如果Avaliable[j]=K,则表示系统中现在空闲的资源 j 的数目为K
1.2 最大需求矩阵Max。这是一个n x m的矩阵,它定义了系统中每一个进程对资源m的最大需求,如果Max[i][j]=K,则表示进程 i 对资源 j 的最大需求为K
1.3 分配矩阵 Allocation。 这是一个n x m的矩阵,它定义了系统中每一类资源当前已经分配给每一个进程的资源数。如果Allocation[i][j]=K,则表示进程 i 当前已分得 j 类资源的数目为K。
1.4 需求矩阵Need。 这也是一个n x m的矩阵, Need[i][j]=K 表示进程 i 仍需要K个系统资源 j 才能完成任务
Need[i][j] = Max[i][j] - Allocation[i][j]
2.银行家算法
设Require[i] 是进程 i 的请求向量,如果Require [i] [j] =K,则表示进程 i 需要资源 j 的数目为K,可以直接将Require设置为Need
2.1 如果Reqiure[i][j] <= Need[i][j],便转向步骤2.2,否则则出错,需求值大于宣布的最大值
2.2 如果Require[i][j] <= Avaliable[i][j],便转向2.3,否则表示系统资源不够,让该进程一直等待
2.3 系统 试探性 的将资源分配给进程 i ,并修改下面数据结构中的数值:
Avaliable[j] -= Require[i][j]
Allocation[i][j] += Require[i][j]
Need[i][j] -= Require[i][j]
2.4 系统执行安全家算法,检查该资源分配以后系统是否处于安全状态,若不安全,则撤回2.3 中的变动,继续查看后续的进程
3.安全性算法
3.1 设置两个向量:
工作向量Work[m],表示系统当前可以提供给进程的m类资源的数目,其初始值与Avaliable数组的值相同
Finish[n]:表示是否足够的进程分配给进程 i ,初始值为false,如果有则Finish[i]的值为true
3.2 从进程集合中找到一个能满足下列条件的进程
1 Finish[i] = false
2 Need[i][j] <= Work[j]
如果存在该进程,则执行3.3,否则执行3.4
3.3 当进程 i 获得资源后,代表其能顺利执行完毕,我们只需释放它原有的分配的资源回系统即可
Work[j] += Allocation[i][j]
Finish[i] = true
继续执行 3.2
3.4 如果所有进程都满足Finish[i] = true ,则表示系统处于安全状态,否则系统处于不安全状态
初始情况
资源情况 Max Allocation Need Avaliable
进程 A B C A B C A B C A B C
p0 7 5 3 0 1 0 7 4 3 3 2 2
p1 3 2 2 2 0 0 1 2 2
p2 9 0 2 3 0 2 6 0 0
p3 2 2 2 2 1 1 0 1 1
p4 4 3 3 0 0 2 4 3 1
很明显p1满足,则 执行中 结果
资源情况 Max Allocation Need Avaliable
进程 A B C A B C A B C A B C
p0 7 5 3 0 1 0 7 4 3 2 0 0
p1 3 2 2 3 2 2 0 0 0
p2 9 0 2 3 0 2 6 0 0
p3 2 2 2 2 1 1 0 1 1
p4 4 3 3 0 0 2 4 3 1
p3 p4执行后并释放
资源情况 Max Allocation Need Avaliable
进程 A B C A B C A B C A B C
p0 7 5 3 0 1 0 7 4 3 7 3 5
p1 3 2 2 0 0 0 0 0 0
p2 9 0 2 3 0 2 6 0 0
p3 2 2 2 0 0 0 0 0 0
p4 4 3 3 0 0 0 0 0 0
依次类推,知道结束
当然,安全序列并不唯一
p1 p3 p4 p0 p2
p1 p3 p2 p4 p1
银行家算法主体躯干
1 for (i = 0; i<n; ++i) 2 { 3 if (judgeNeed(i))//判断所需资源是否超过所需的最大值 4 { 5 if (judgeAvaliable(i))//判断是否有足够的空闲资源 6 { 7 for (int j = 0; j<m; ++j) 8 { 9 Avaliable[j] -= require[i][j]; 10 Allocation[i][j] += require[i][j]; 11 Need[i][j] -= require[i][j]; 12 } 13 14 if (!systemSafe(i)) 15 { 16 for (int j = 0; j<m; ++j) 17 { 18 Avaliable[j] += require[i][j]; 19 Allocation[i][j] -= require[i][j]; 20 Need[i][j] += require[i][j]; 21 } 22 } 23 else 24 { 25 cout << "safe" << endl; 26 break; 27 } 28 29 clearRequire();//进行审核下一次的请求 30 } 31 } 32 33 } 34 35 if (i == n) 36 cout << "无分配方案" << endl;
安全监测算法
bool systemSafe(int flag) { bool Finish[n] = { false }; for (int i = 0; i<m; ++i) Work[i] = Avaliable[i]; //将在试探分配过的资源回收 for (int j = 0; j<m; ++j) Work[j] += Allocation[flag][j]; Finish[flag] = true;//表名试探资源已经释放完毕 int index = getFinishFalse(0, Finish);//查找第一个为false的进程 showResult();//打印第一次试探后的结果 while (1) { //如果还存在一直等待的进程 if (index != -1) { //判断该进程所需的资源数是否小于当前拥有资源数 if (allNeedLessWork(index, Work, Finish) && Finish[index]==false) { for (int j = 0; j < m; ++j) Work[j] += Allocation[index][j]; Finish[index] = true; index = 0; showResult();//打印此时的结果 } else index = getFinishFalse(index+1, Finish);//因所需资源过大而需要等待,所以必须在该进程之后查找,否则会再次查找得到该进程,进入死循环 } else { if (allTrue(Finish)) return true; else return false; } } }
注:部分函数省略