银行家算法简述
银行家算法是最有名的避免死锁的策略(区别于死锁的预防)。
该策略以银行的借贷策略为基础建立模型。系统掌握有限个数的资源,用于提供给不同的进程。如果所有进程都能得到他们需要得最大资源数,并运行完成、归还资源,则该系统是安全的。
算法流程描述
1、·首先对进行当前的系统状态进行初始化:先输入系统所拥有的每种资源的数量(Resource)、当前运行的进程对每种资源的最大需求量(MaxNeed)和每个进程已分配到的每种资源的数量(Allocation),就可以计算出每个进程还需要的资源量(Need)及系统还未分配的资源量(Available)。至此,对系统状态的初始化完成。
2、系统进行安全判定。这里用Work保存系统运行中Available的动态过程。
先将每个进程的状态(Finish)初始化为0。依次对比Need与Work中资源数目,当Work里的资源能够满足Need中某一进程对资源的需求量时,将Finish里该进程赋值为1,该进程转化为完成时。将该进程释放的资源给Work(Work[j] += Allocation[i][j];),保存进程下标。
若全部进程均运行完成,则系统处于安全状态,输出安全序列。
完整代码:
#include <stdio.h>
#include<string.h>
#define R 3 //资源数
#define P 4 //进程数
int Resource[R];//资源总量
int Available[R];//还剩下
int MaxNeed[P][R];//每个进程最大需要
int Allocation[P][R];//已分配
int Need[P][R];//还需要
int Work[R];//保存工作时剩余资源数量
int Finish[P];//保存工作过程中进程的状态
int SafeList[P]; //存放安全序列的下标序列
//初始化:先输入 Resource、MaxNeed和 Allocation,再计算出 Need、Available。
void Initial(){
int i, j;
printf("请分别输入%d种资源的数量:\n",R);
for (i = 0; i < R; i++) {
scanf_s("%d", &Resource[i]);
Available[i] = Resource[i];//目前还未分配,将资源总量与未分配数同步
}
printf("当前运行了%d个进程,请输入每个进程对应的%d种资源的最大需求量:\n",P,R);
for (j = 0; j < P; j++)
for (i = 0; i < R; i++)
scanf_s("%d", &MaxNeed[j][i]);
printf("请输入这%d个进程目前已分配的每种资源的数量:\n",P);
for (j = 0; j < P; j++)
for (i = 0; i < R; i++)
scanf_s("%d", &Allocation[j][i]);
//计算每个进程还需要的每种资源数量
for (j = 0; j < P; j++)
for (i = 0; i < R; i++)
Need[j][i] = MaxNeed[j][i] - Allocation[j][i];
//计算每种资源还剩下的资源总量
for (j = 0; j < R; j++)
for (i = 0; i < P; i++)
Available[j] = Available[j] - Allocation[i][j];
}
//格式化输出
void Printf(int num[R]) {
int j;
for (j = 0; j < R; j++) {
printf("%-4d",num[j]);
}
printf("|");
}
//输出
void PrintState(){
int i,j;
printf("当前状态:\n|进程|最大需求 已分配 还需要 还剩下 | \n");
for (i = 0; i < P; i++){
printf("|P%-3d|",i);
Printf(MaxNeed[i]);
Printf(Allocation[i]);
Printf(Need[i]);
if (i == 0) {
Printf(Available);
printf("\n");
}
else
printf(" |\n");
}
}
//判断,返回同时满足Finish[i]=0(即进程未运行完成)及Need[i]≤Work的进程号 i,修改i的finish完成状态。
int Judge(){
int i, j, Rnum;//记资源满足数
for (i = 0; i < P; i++){
for (j = 0, Rnum = 0; j < R; j++) {
if (Finish[i] == 0 && Need[i][j] <= Work[j])
Rnum++;
}
if (Rnum == R) {
for (j = 0; j < R; j++)
Work[j] += Allocation[i][j];//获取已完成的进程释放的资源
Finish[i] = 1;//修改该进程状态
return i;
}
}
return -1;
}
//检测当前状态是否安全。循环判断,当所有进程均释放完毕,则系统安全,将保存的安全序列输出
int Y_NSafe(){
int i, SerialNum;//暂存下标
for (i = 0; i < R; i++)
Work[i] = Available[i];//还剩下
memset(Finish,0,sizeof(Finish));
for (i = 0; i < P; i++){
for (int j = 0; j < R; j++)
if (Available[j] < 0) {
printf("已分配的%d资源数量大于系统所拥有的该资源总量,系统错误\n", j);
return 0;
}
for (int j = 0; j < R; j++){
if (MaxNeed[i][j] > Resource[j]) {
printf("%d进程对%d号资源的最大需求数量大于系统所拥有的%d号资源的总量!\n",i,j,j);
}
}
for (int j = 0; j < R; j++) {
if (Need[i][j] > MaxNeed[i][j]) {
printf("您请求的%d号资源大于%d进程对%d号资源的最大需求\n",j,i,j);
}
}
SerialNum = Judge();
//如果进程完成,则将该进程下标存入安全序列
if (SerialNum >= 0){
SafeList[i] = SerialNum;
}
else
return 0;
}
//判断进程是否全部完成
return 1;
}
//输出安全序列
void printList(){
int i0, i, j;
printf("\n安全序列如下:\n|进程|已分配 |还需要 |还剩下 |\n");
for (j = 0; j < R; j++){
Work[j] = Available[j];
}
for (i0 = 0; i0 < P; i0++) {
for (j = 0; j < R; j++) {
Work[j] += Allocation[SafeList[i0]][j];
Allocation[SafeList[i0]][j] = 0;
Need[SafeList[i0]][j] = 0;
}
for (i = 0; i < P; i++) {
printf("|P%-3d|",i);
Printf(Allocation[i]);
Printf(Need[i]);
if (i == 0)
Printf(Work);
printf("\n");
}
printf("\n");
}
}
int main(){
int i;
Initial();
PrintState();
getchar();
if (Y_NSafe() == 0){
printf("当前系统状态不安全\n");
}else {
printf("\n当前系统状态安全\n");
printList();
}
printf("\n点击回车退出\n");
getchar();
}