银行家算法浅析及C++代码实现

1.银行家算法的作用

进程在资源分配的过程中,如果分配顺序不当,会陷入死锁,为了避免死锁,引入了银行家算法

2.银行家算法的原理

为进程试分配资源,判断得到资源后是否存在一个安全序列(进程组中的进程能够按照一定顺序向前推进的序列),如果存在安全序列,说明该分配方法合理,否则进行下一种分配方案。

1) 执行流程

第一步:判断进程pid请求的资源数是否大于当前需要的资源数,如果大于不执行分配,否则进行下一步;
第二步:判断进程pid请求的资源数是否大于当前可利用的资源数,如果大于不执行分配,否则进行下一步;
第三步:试分配资源;
第四步:执行安全性算法,检查本次资源分配后是否处于安全状态,安全则正式分配资源,否则本次试分配作废,恢复之前的资源分配状态,让当前进程等待。

2) 核心:安全性算法

  1. 为所有进程建立一个标记数组Finish,标记进程是否已经成功得到所需资源,全部初始化为false;建立工作向量数组Work,初始化为当前可利用的资源数;
  2. 从进程集合中找到一个满足下面条件的进程:
    a. Finish[i] = false;
    b. 当前进程需要的资源小于等于工作向量中对应的资源数;
    如果能找到,则继续下一步,找不到执行步骤4;
  3. 进程获得资源,使用资源结束后释放资源,继续执行步骤2;
  4. 如果所有进程都已经成功得到所有资源,表示当前系统处于安全状态,否则系统处于不安全状态。

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;
}

测试

在这里插入图片描述
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值