银行家算法C++代码实现

一、算法介绍

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

​ 多个进程动态地共享系统的资源可能会产生死锁现象。死锁的产生,必须同时满足四个条件,第一个是互斥条件,即一个资源每次只能由一个进程占用;第二个为请求和保持条件,即一个进程请求资源不能满足时,它必须等待,但它仍继续保持已得到的所有其它资源;第三个是不剥夺条件,任何一个进程不能抢占另一个进程已经获得且未释放的资源;第四个为循环等待条件,系统中存在若干个循环等待的进程,即其中每一个进程分别等待它前一个进程所持有的资源,防止死锁的机构只须确保上述四个条件之一不出现,则系统就不会发生死锁。在实验中假定系统中任一资源在每一时刻只能由一个进程使用,任何进程不能抢占其它进程正在使用的资源,当进程得不到资源时必须等待。因此只要资源分配策略能保证进程不出现循环等待,则系统就不会发生死锁。

二、算法背景简介

​ 在银行中,客户申请贷款的数量是有限的,每个客户在第一次申请贷款时要声明完成该项目所需的最大资金量,在满足所有贷款要求时,客户应及时归还。银行家在客户申请的贷款数量不超过自己拥有的最大值时,都应尽量满足客户的需要。在这样的描述中,银行家就好比操作系统,资金就是资源,客户就相当于要申请资源的进程。

​ 银行家算法是一种最有代表性的避免死锁的算法。在避免死锁方法中允许进程动态地申请资源,但系统在进行资源分配之前,应先计算此次分配资源的安全性,若分配不会导致系统进入不安全状态,则分配,否则等待。为实现银行家算法,系统必须设置若干数据结构。

​ 要解释银行家算法,必须先解释操作系统安全状态和不安全状态。

​ 安全序列是指一个进程序列{P1,…,Pn}是安全的,即对于每一个进程Pi(1≤i≤n),它以后尚需要的资源量不超过系统当前剩余资源量与所有进程Pj (j < i )当前占有资源量之和。

三、测试数据

测试题目如下图所示:
在这里插入图片描述

测试数据文件banker.dat:
在这里插入图片描述

四、代码实现

banker.cpp

#include<iostream>
#include<fstream>
#include<Windows.h>
#include<queue>
using namespace std;
const int M = 100;

int pro = 0;//线程数目
int source = 0;//资源数目
queue<int> safeq;//安全序列
//安全性算法 
bool check(int available[], int max[][M], int allocation[][M], int need[][M]) {
	bool finished[100] = { false };//标记某一线程是否已经完成所有资源的借贷
	int available2[100];//可利用资源向量available 
	int max2[100][100];//最大需求矩阵max 
	int allocation2[100][100];//分配矩阵allocation 
	int need2[100][100];//需求矩阵need
	//为四个矩阵赋值
	for (int i = 0; i < pro; i++) {
		for (int j = 0; j < source; j++) {
			available2[j] = available[j];
			max2[i][j] = max[i][j];
			allocation2[i][j] = allocation[i][j];
			need2[i][j] = need[i][j];
		}
	}

	while (1) {
		int sumNeed = 0;
		for (int i = 0; i < pro; i++) {
			for (int j = 0; j < source; j++) {
				sumNeed += need2[i][j];
			}
			if (sumNeed != 0) {
				break;
			}
		}
		//如果need矩阵中所有的值都为0,即所有的需求都已经被满足
		if (sumNeed == 0) {
			return true;
		}
		//用于标记是否满足了某个线程的请求,如果都无法满足,则出现了不安全队列
		bool needflag = false;
		for (int i = 0; i < pro; i++) {
			bool flag = true;
			for (int j = 0; j < source; j++) {
				if (need2[i][j] > available2[j]) {
					flag = false;
				}
			}
			if (flag && !finished[i]) {
				needflag = true;
				safeq.push(i);
				for (int j = 0; j < source; j++) {
					allocation2[i][j] = allocation2[i][j] + need2[i][j];
					need2[i][j] = 0;
					available2[j] = available2[j] + allocation2[i][j];
					finished[i] = true;
				}

			}
			else {
				continue;
			}

		}
		if (!needflag) {
			cout << "出现了不安全序列!!\n";
			return false;
		}
	}


	return false;
}


//主函数
int main() {
	int available[100];//可利用资源向量available 
	int max[100][100];//最大需求矩阵max 
	int allocation[100][100];//分配矩阵allocation 
	int need[100][100];//需求矩阵need

	cout << "正在读取数据文件\n";
	Sleep(2000);
	ifstream inFile;
	inFile.open("banker.dat");
	if (!inFile.is_open())
		cout << "文件打开时候出错!!" << endl;
	inFile >> pro >> source;
	cout << "共有" << pro << "个线程," << source << "种资源\n";

	if (pro >= 100 || source >= 100) {
		cout << "输入的线程或资源数目过大!!";
		exit(0);
	}

	while (!inFile.eof()) {           // 若未到文件结束一直循环

		//读入available
		for (int i = 0; i < pro; i++) {
			inFile >> available[i];
		}

		//读入max
		for (int i = 0; i < pro; i++) {
			for (int j = 0; j < source; j++) {
				inFile >> max[i][j];
			}
		}

		//读入allocation
		for (int i = 0; i < pro; i++) {
			for (int j = 0; j < source; j++) {
				inFile >> allocation[i][j];
			}
		}

		//读入need
		for (int i = 0; i < pro; i++) {
			for (int j = 0; j < source; j++) {
				need[i][j] = max[i][j] - allocation[i][j];
			}
		}
	}
	inFile.close();

	//打印提示信息
	cout << "************************************************\n";
	cout << "        操作系统实验模拟银行家算法\n";
	cout << "        作者:CSDN Carmelo_7 主页: https://blog.csdn.net/Carmelo_7?spm=1000.2115.3001.5343\n";
	cout << "************************************************\n";

	cout << "AVAILABLE:\n";
	for (int i = 0; i < pro; i++) {
		cout << available[i] << " ";
	}
	cout << "\n";
	cout << "MAX:\n";
	for (int i = 0; i < pro; i++) {
		for (int j = 0; j < source; j++) {
			cout << max[i][j] << " ";
		}
		cout << "\n";
	}
	cout << "ALLOCATION:\n";
	for (int i = 0; i < pro; i++) {
		for (int j = 0; j < source; j++) {
			cout << allocation[i][j] << " ";
		}
		cout << "\n";
	}
	cout << "NEED:\n";
	for (int i = 0; i < pro; i++) {
		for (int j = 0; j < source; j++) {
			cout << need[i][j] << " ";
		}
		cout << "\n";
	}
	//检查当前状态是否安全
	if (check(available, max, allocation, need) == true) {
		cout << "操作系统现有状态安全!\n" << "安全序列为:";
		while (!safeq.empty()) {
			cout << "P" << safeq.front() << " ";
			safeq.pop();
		}
	}
	else {
		cout << "操作系统现有状态不安全!\n";
		exit(0);
	}

	//线程开始请求相应的资源
	bb:
	while (true) {
		int proNo;
		int request[100];
		cout << "输入请求的线程号:";
		cin >> proNo;

		for (int i = 0; i < source; i++) {
			cout << "\n输入线程对于资源" << i << "的请求数量:\n";
			cin >> request[i];
		}
		//复制一份四个矩阵
		int available2[100];//可利用资源向量available 
		int max2[100][100];//最大需求矩阵max 
		int allocation2[100][100];//分配矩阵allocation 
		int need2[100][100];//需求矩阵need
		//为四个矩阵赋值
		for (int i = 0; i < pro; i++) {
			for (int j = 0; j < source; j++) {
				available2[j] = available[j];
				max2[i][j] = max[i][j];
				allocation2[i][j] = allocation[i][j];
				need2[i][j] = need[i][j];
			}
		}
		for (int i = 0; i < source; i++) {
			if (available2[i]<request[i]) {
				cout << "操作系统现有状态不安全!\n";
				goto bb;
			}
		}
		for (int i = 0; i < source; i++) {
			available2[i] = available2[i] - request[i];
			allocation2[proNo][i] = allocation[proNo][i]+ request[i];
			need2[proNo][i] = need[proNo][i]- request[i];
		}
		//检查接受request请求后状态是否安全
		if (check(available2, max2, allocation2, need2) == true) {
			cout << "操作系统现有状态安全!\n" << "安全序列为:";
			while (!safeq.empty()) {
				cout << "P" << safeq.front() << " ";
				safeq.pop();
			}
		}
		else {
			cout << "操作系统现有状态不安全!\n";
			exit(0);
		}

		return 0;
	}
}

测试数据文件banker.dat:

4 4
1 5 2 0
0 0 1 2
1 7 5 0
2 3 5 6
0 6 5 6
0 0 1 2
1 0 0 0
1 3 5 4
0 0 1 4
  • 9
    点赞
  • 58
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
银行家算法(Banker's Algorithm)是一种死锁避免算法,用于避免并发系统中的死锁问题。它由艾德加·沃茨·迪科斯基(Edsger W. Dijkstra)于1965年提出。银行家算法的主要思想是在进程请求资源时,先判断该请求是否会导致系统进入不安全状态,如果不会,则分配资源;否则,让进程等待,直到请求满足安全条件。 以下是银行家算法C++代码实现: ```cpp #include <iostream> #include <vector> #include <algorithm> using namespace std; // 定义进程状态 enum ProcessState { Ready, // 就绪 Running, // 运行 Blocked, // 阻塞 Dead // 终止 }; // 定义进程结构体 struct Process { int id; // 进程ID ProcessState state; // 进程状态 vector<int> max_res; // 进程最大需求资源量 vector<int> need_res; // 进程还需资源量 vector<int> allocation_res; // 进程已分配资源量 }; // 定义银行家算法类 class Banker { private: int process_num; // 进程数量 int res_num; // 资源种类数量 vector<int> available_res; // 系统可用资源量 vector<Process> processes; // 进程列表 public: Banker(int pnum, int rnum, vector<int> available, vector<Process> p) : process_num(pnum), res_num(rnum), available_res(available), processes(p) {} // 银行家算法判断 bool isSafe() { vector<int> work(available_res.begin(), available_res.end()); // 工作向量 vector<bool> finish(process_num, false); // 完成进程标记 vector<int> safe_sequence; // 安全序列 int count = 0; // 已完成进程数 while (count < process_num) { bool found = false; for (int i = 0; i < process_num; ++i) { if (finish[i] == false) { bool finishable = true; for (int j = 0; j < res_num; ++j) { if (processes[i].need_res[j] > work[j]) { finishable = false; break; } } if (finishable) { for (int j = 0; j < res_num; ++j) { work[j] += processes[i].allocation_res[j]; } finish[i] = true; safe_sequence.push_back(i); found = true; count++; } } } if (found == false) { return false; } } cout << "Safe sequence: "; for (int i = 0; i < process_num; ++i) { cout << "P" << safe_sequence[i]; if (i != process_num - 1) { cout << " -> "; } } cout << endl; return true; } // 进程请求资源 bool requestRes(int pid, vector<int> request) { vector<int> work(available_res.begin(), available_res.end()); // 工作向量 vector<int> finish(process_num, false); // 完成进程标记 // 判断请求是否满足需求 for (int i = 0; i < res_num; ++i) { if (request[i] > processes[pid].need_res[i]) { return false; } } // 判断请求是否满足可用资源量 for (int i = 0; i < res_num; ++i) { if (request[i] > available_res[i]) { return false; } } // 模拟分配资源 for (int i = 0; i < res_num; ++i) { available_res[i] -= request[i]; processes[pid].allocation_res[i] += request[i]; processes[pid].need_res[i] -= request[i]; } // 判断是否会导致系统不安全 int count = 0; while (count < process_num) { bool found = false; for (int i = 0; i < process_num; ++i) { if (finish[i] == false) { bool finishable = true; for (int j = 0; j < res_num; ++j) { if (processes[i].need_res[j] > work[j]) { finishable = false; break; } } if (finishable) { for (int j = 0; j < res_num; ++j) { work[j] += processes[i].allocation_res[j]; } finish[i] = true; found = true; count++; } } } if (found == false) { // 分配资源后会导致系统不安全,回滚分配 for (int i = 0; i < res_num; ++i) { available_res[i] += request[i]; processes[pid].allocation_res[i] -= request[i]; processes[pid].need_res[i] += request[i]; } return false; } } return true; } }; int main() { // 测试数据 int process_num = 5; int res_num = 3; vector<int> available_res {3, 3, 2}; vector<Process> processes { {0, Ready, {7, 5, 3}, {7, 5, 3}, {0, 0, 0}}, {1, Ready, {3, 2, 2}, {3, 2, 2}, {0, 0, 0}}, {2, Blocked, {9, 0, 2}, {9, 0, 2}, {0, 0, 0}}, {3, Running, {2, 2, 2}, {2, 2, 2}, {0, 0, 0}}, {4, Ready, {4, 3, 3}, {4, 3, 3}, {0, 0, 0}} }; // 初始化银行家算法 Banker banker(process_num, res_num, available_res, processes); // 测试安全性 banker.isSafe(); // 测试进程请求资源 int pid = 1; vector<int> request {1, 0, 2}; if (banker.requestRes(pid, request)) { cout << "Process P" << pid << " request success!" << endl; } else { cout << "Process P" << pid << " request failed!" << endl; } return 0; } ``` 在上面的代码中,我们定义了一个`Process`结构体来表示进程,包含了进程ID、状态、最大需求资源量、还需资源量和已分配资源量等信息。我们还定义了一个`Banker`类来实现银行家算法,构造函数中需要传入进程数量、资源种类数量、系统可用资源量和进程列表等参数。`isSafe()`函数用于判断系统是否安全,而`requestRes()`函数用于模拟进程请求资源的情况。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值