1.银行家算法的作用
进程在资源分配的过程中,如果分配顺序不当,会陷入死锁,为了避免死锁,引入了银行家算法
2.银行家算法的原理
为进程试分配资源,判断得到资源后是否存在一个安全序列(进程组中的进程能够按照一定顺序向前推进的序列),如果存在安全序列,说明该分配方法合理,否则进行下一种分配方案。
1) 执行流程
第一步:判断进程pid请求的资源数是否大于当前需要的资源数,如果大于不执行分配,否则进行下一步;
第二步:判断进程pid请求的资源数是否大于当前可利用的资源数,如果大于不执行分配,否则进行下一步;
第三步:试分配资源;
第四步:执行安全性算法,检查本次资源分配后是否处于安全状态,安全则正式分配资源,否则本次试分配作废,恢复之前的资源分配状态,让当前进程等待。
2) 核心:安全性算法
- 为所有进程建立一个标记数组Finish,标记进程是否已经成功得到所需资源,全部初始化为false;建立工作向量数组Work,初始化为当前可利用的资源数;
- 从进程集合中找到一个满足下面条件的进程:
a. Finish[i] = false;
b. 当前进程需要的资源小于等于工作向量中对应的资源数;
如果能找到,则继续下一步,找不到执行步骤4; - 进程获得资源,使用资源结束后释放资源,继续执行步骤2;
- 如果所有进程都已经成功得到所有资源,表示当前系统处于安全状态,否则系统处于不安全状态。
3.银行家算法代码实现及测试
数据结构
processNum:进程数
resourceNum:资源数
MaxNeeds[processNum][resourceNum]:最大需求矩阵
MaxNeeds[i][j]:进程i对于资源j的最大需求数
Allocation[processNum][resourceNum]:分配矩阵
Allocation:分配给进程i的j类资源数量
Needs[processNum][resourceNum]:需求矩阵
Needs[i][j]:进程i还需要j类资源的数量
Avaliable[resourceNum]:可利用资源
Avaliable[j]:j类资源的剩余数量
Finish[processNum]:进程是否都能成功分配资源
Finish[i]:进程i是否能成功分配资源
安全性算法的实现方式
深度优先搜索,在本轮搜索过程中找到满足分配条件的进程,对资源进行试分配,然后下一轮搜索找满足条件的其它进程,当路径集合中的进程数等于已知的总进程数时,将当前搜索得到的安全序列放入总集合中。
源码
Banker.h:
#pragma once
#include <vector>
using std::vector;
//银行家算法
//Finish集合是否全部为true
bool IsAllTrue(vector<bool>& Finish)
{
bool ret = true;
for (auto e : Finish)
{
if (e == false)
{
ret = false;
break;
}
}
return ret;
}
//找到所有可行的分配方法
//参数如下:
//Needs:需求矩阵
//Allocation:分配矩阵
//Avaliable:可利用资源
//Finish:进程是否都能成功分配资源
//curProcessSum:当前试分配过资源的进程数
//allPaths:所有的安全序列
//path:一条安全序列
void findValidMethod(vector<vector<int>>& Needs, vector<vector<int>>& Allocation,
vector<int>& Avaliable, vector<bool>& Finish, int curProcessSum,
vector<vector<int>>& allPaths, vector<int>& path)
{
int processNum = Finish.size(); //进程数量
int resourceNum = Avaliable.size(); //资源数量
//递归出口
if (curProcessSum == processNum && IsAllTrue(Finish))
{
allPaths.emplace_back(path);
return;
}
int idx = 0;
//查找可以分配资源的进程并进行试分配
while (idx < processNum)
{
if (Finish[idx] == false)
{
bool CanAllocate = true;
//检查资源是否可以分配
for (int i = 0; i < resourceNum; ++i)
{
//需要的资源大于可利用资源数
if (Needs[idx][i] > Avaliable[i])
{
CanAllocate = false;
break;
}
}
//资源可以分配,进行试分配
if (CanAllocate)
{
for (int i = 0; i < resourceNum; ++i)
{
Avaliable[i] += Allocation[idx][i];
}
Finish[idx] = true;
path.emplace_back(idx);
//为下一个进程试分配资源
findValidMethod(Needs, Allocation, Avaliable, Finish, curProcessSum + 1, allPaths, path);
//回退
Finish[idx] = false;
path.pop_back();
for (int i = 0; i < resourceNum; ++i)
{
Avaliable[i] -= Allocation[idx][i];
}
}
}
++idx;
}
}
main.cpp
#include "Banker.h"
#include <iostream>
#include <vector>
#include <cstdlib>
/*
银行家算法模拟实现
*/
using namespace std;
//欢迎界面
void Welcome()
{
cout << "-------------------- 欢迎您,尊敬的银行家! ---------------------" << endl;
cout << "----------- 请开始进行分配并保证贷出去的钱都能收回来 ------------" << endl;
cout << "---------------- 请开始您的工作 ---------------------------" << endl;
}
void Menu()
{
cout << "操作指令如下:" << endl;
cout << "0 : 退出工作" << endl;
cout << "1: 打印此时所有的安全序列" << endl;
cout << "2: 请求资源并打印安全序列" << endl;
}
int main()
{
Welcome();
//进程数和资源数
int processNum, resourceNum;
cout << "请输入进程数和资源数: " << endl;
cin >> processNum >> resourceNum;
//空闲资源持有数
vector<int> Avaliable(resourceNum);
cout << "请输入每种资源的现在剩余数Avaliable:" << endl;
for (int i = 0; i < resourceNum; ++i)
{
cin >> Avaliable[i];
}
//最大需求矩阵
vector<vector<int>> MaxNeeds(processNum, vector<int>(resourceNum));
cout << "请从第一个进程到最后一个进程输入每种资源的最大需求数量MaxNeeds:" << endl;
for (int i = 0; i < processNum; ++i)
{
for (int j = 0; j < resourceNum; ++j)
{
cin >> MaxNeeds[i][j];
}
}
//分配矩阵
vector<vector<int>> Allocation(processNum, vector<int>(resourceNum));
cout << "请从第一个进程到最后一个进程输入每种资源的当前持有数量Allocation: " << endl;
for (int i = 0; i < processNum; ++i)
{
for (int j = 0; j < resourceNum; ++j)
{
cin >> Allocation[i][j];
}
}
//需求矩阵
vector<vector<int>> Needs(processNum, vector<int>(resourceNum));
for (int i = 0; i < processNum; ++i)
{
for (int j = 0; j < resourceNum; ++j)
{
//当前资源的需求 = 最大需求 - 已经分配到的资源
Needs[i][j] = MaxNeeds[i][j] - Allocation[i][j];
}
}
//进程是否能成功分配资源,初始化为false
vector<bool> Finish(processNum, false);
while (1)
{
Menu();
int choice;
cout << "请输入操作指令: ";
cin >> choice;
//退出操作
if (choice == 0)
{
cout << "欢迎再次开始工作,尊敬的银行家!" << endl;
exit(-1);
}
//打印所有的安全序列,如果有的话
else if (choice == 1)
{
vector<int> path; //一条可行的分配方法
vector<vector<int>> allPaths; //所有可行的分配方法
//将Finish置为false
for (int i = 0; i < processNum; ++i)
{
Finish[i] = false;
}
//深度优先找到所有的安全序列
findValidMethod(Needs, Allocation, Avaliable, Finish, 0, allPaths, path);
if (allPaths.empty())
{
cout << "不存在安全序列!" << endl;
}
else
{
cout << "安全序列如下: " << endl;
for (auto onePath : allPaths)
{
for (int i = 0; i < onePath.size() - 1; ++i)
{
cout << onePath[i] << " ---> ";
}
cout << onePath[onePath.size() - 1] << endl;
}
}
system("pause");
system("cls");
}
//执行请求资源操作
else if (choice == 2)
{
vector<int> Request(resourceNum);
int pid;
cout << "请输入当前请求的进程编号(从0开始) : ";
cin >> pid;
if (pid < 0 || pid >= processNum)
{
cout << "输入进程的编号不存在,请重新请求" << endl;
system("pause");
system("cls");
continue;
}
cout << "请输入当前进程请求的资源数量: ";
for (int i = 0; i < resourceNum; ++i)
{
cin >> Request[i];
}
//将Finish置为false
for (int i = 0; i < processNum; ++i)
{
Finish[i] = false;
}
bool IsRequestValid = true; //请求是否合理
//检查请求的合理性
for (int i = 0; i < resourceNum; ++i)
{
if (Request[i] > Needs[pid][i])
{
IsRequestValid = false;
break;
}
if (Request[i] > Avaliable[i])
{
IsRequestValid = false;
break;
}
}
if (IsRequestValid == false)
{
cout << "当前进程请求的资源不合理,不能予以分配" << endl;
}
else
{
//找出所有的安全序列
vector<int> path; //一条可行的分配方法
vector<vector<int>> allPaths; //所有可行的分配方法
//将Finish置为false
for (int i = 0; i < processNum; ++i)
{
Finish[i] = false;
}
//深度优先找到所有的安全序列
findValidMethod(Needs, Allocation, Avaliable, Finish, 0, allPaths, path);
if (allPaths.empty())
{
cout << "资源请求合理,但不存在安全序列!" << endl;
}
else
{
cout << "资源请求合理,安全序列如下: " << endl;
for (auto onePath : allPaths)
{
for (int i = 0; i < onePath.size() - 1; ++i)
{
cout << onePath[i] << " ---> ";
}
cout << onePath[onePath.size() - 1] << endl;
}
}
}
}
else
{
cout << "输入有误,请重新输入" << endl;
}
system("pause");
system("cls");
}
return 0;
}
测试