银行家算法(安全序列)

银行家算法

银行家算法(Banker's Algorithm)是一个避免死锁(Deadlock)的著名算法,是由艾兹格·迪杰斯特拉在1965年为T.H.E系统设计的一种避免死锁产生的算法。它以银行借贷系统的分配策略为基础,判断并保证系统的安全运行。

安全状态

如果存在一个由系统中所有进程构成的安全序列P1,…,Pn,则系统处于安全状态。安全状态一定是没有死锁发生。

不安全状态

不存在一个安全序列。不安全状态不一定导致死锁。

数据结构

1)可利用资源向量Available
是个含有m个元素的数组,其中的每一个元素代表一类可利用的资源数目。如果Available[j]=K,则表示系统中现有Rj类资源K个。
2)最大需求矩阵Max
这是一个n×m的矩阵,它定义了系统中n个进程中的每一个进程对m类资源的最大需求。如果Max[i,j]=K,则表示进程i需要Rj类资源的最大数目为K。
3)分配矩阵Allocation
这也是一个n×m的矩阵,它定义了系统中每一类资源当前已分配给每一进程的资源数。如果Allocation[i,j]=K,则表示进程i当前已分得Rj类资源的 数目为K。
4)需求矩阵Need。
这也是一个n×m的矩阵,用以表示每一个进程尚需的各类资源数。如果Need[i,j]=K,则表示进程i还需要Rj类资源K个,方能完成其任务。
Need[i,j]=Max[i,j]-Allocation[i,j]

算法原理

我们可以把操作系统看作是银行家,操作系统管理的资源相当于银行家管理的资金,进程向操作系统请求分配资源相当于用户向银行家贷款。
为保证资金的安全,银行家规定:
(1) 当一个顾客对资金的最大需求量不超过银行家现有的资金时就可接纳该顾客;
(2) 顾客可以分期贷款,但贷款的总数不能超过最大需求量;
(3) 当银行家现有的资金不能满足顾客尚需的贷款数额时,对顾客的贷款可推迟支付,但总能使顾客在有限的时间里得到贷款;
(4) 当顾客得到所需的全部资金后,一定能在有限的时间里归还所有的资金.
操作系统按照银行家制定的规则为进程分配资源,当进程首次申请资源时,要测试该进程对资源的最大需求量,如果系统现存的资源可以满足它的最大需求量则按当前的申请量分配资源,否则就推迟分配。当进程在执行中继续申请资源时,先测试该进程本次申请的资源数是否超过了该资源所剩余的总量。若超过则拒绝分配资源,若能满足则按当前的申请量分配资源,否则也要推迟分配。****

代码

(样例是按照课本西安电子科技大学第四版的)

#include <iostream>
#include <algorithm>
using namespace std;
const int N = 1e3 + 10;
int Avaialbe[N] = { 3, 3, 2 };//可利用资源向量
int Max[N][3] = { {7, 5, 3}, {3, 2, 2}, {9, 0, 2}, {2, 2, 2,}, {4, 3, 3} };//最大需求资源矩阵
int Allocation[N][3] = { {0, 1, 0}, {2, 0, 0}, {3, 0, 2}, {2, 1, 1}, {0, 0 , 2} };//已经分配的资源矩阵
int Need[N][3] = { {7, 4, 3}, {1, 2, 2}, {6, 0, 0}, {0, 1, 1}, {4, 3, 1} };//还需要的资源矩阵
int n, Request[3];
int path[5];//安全序列
int st[5];//分配标志位
void display(int i) {
	cout << "P" << i << endl;
	cout << "Avaialbe\tNeed\tAllocation\tAvaialbe+Allocation" << endl;
	for (int j = 0; j < 3; j++)cout << Avaialbe[j] << ' ';
	cout << "\t\t";
	for (int j = 0; j < 3; j++)cout << Need[i][j] << ' ';
	cout << "\t";
	for (int j = 0; j < 3; j++)cout << Allocation[i][j] << ' ';
	cout << "\t\t";
	for (int j = 0; j < 3; j++)cout << Avaialbe[j] + Allocation[i][j] << ' ';
	cout << endl;
}
bool isSafe(int u) {//安全性算法检查  如果存在安全序列则返回true 安全序列在path数组里
	if (u >= 5) {
		return true;
	}
	bool flag = 0;
	for (int i = 0; i < 5; i++) {//检查是否处于安全状态
		if (!st[i]) {//当前进程还没有满足
if (Need[i][0] <= Avaialbe[0] && Need[i][1] <= Avaialbe[1] && Need[i][2] <= Avaialbe[2] && !st[i]) {//可以分配
				display(i);//输出当前进程状态
				for (int j = 0; j < 3; j++) {//分配给当前进程资源
					Avaialbe[j] += Allocation[i][j];
					Allocation[i][j] = 0;
				}
				flag = 1;
				st[i] = 1;
				path[u] = i;
				break;
			}
		}
	}
	if (flag) {
		isSafe(u + 1);
	}
	else return false;
}
bool Safe() {//银行家算法
	for (int i = 0; i < 3; i++) {//不能大于开始声明的请求最大值
		if (Request[i] > Max[n][i]) {
			cout << "不能大于开始声明的请求最大值" << endl;
			return false;
		}
	}
	for (int i = 0; i < 3; i++) {//不能大于当前系统剩余资源
		if (Request[i] > Avaialbe[i]) {
			cout << "不能大于当前系统剩余资源";
			return false;
		}
	}
	for (int i = 0; i < 3; i++) {//尝试分配给该进程资源
		Allocation[n][i] += Request[i];
		Avaialbe[i] -= Request[i];
		Need[n][i] -= Request[i];
	}
	if (isSafe(0))return true;//分配资源之后系统不能处于不安全状态
	return false;

}
int main() {
	//	freopen("a.txt", "r", stdin);
	cout << "请输入进程号(0~4):\n";
	cin >> n;
	cout << "请输入该进程需要请求的三个资源:\n";
	for (int i = 0; i < 3; i++)cin >> Request[i];
	if (Safe()) {//执行安全检查算法成功
		cout << "\n存在一个安全序列:";
		for (int i = 0; i < 5; i++) {
			cout << path[i] << ' ';
		}
		cout << "\n所以该系统是安全的, 可以将资源分配给该进程!\n";
	}
	else {//执行安全性算法失败
		cout << "\n不存在一个安全序列, 不能将资源分配给改进程!\n";
	}
}

posted @ 2021-12-17 08:40  梨花满地  阅读(2219)  评论(0)    收藏  举报