银行家算法

emmmm。。这个是很久以前做的 为了防止文件丢失 直接把实训报告贴在这以作保存

用程序实现银行家算法

 

 

1.   课程设计内容

整个银行家算法程序包括

void showstart(int m, int n);// 以数组形式显示出m 个进程对 n 类资源已有资源

void showneed(int m, intn);// 以数组形式显示出 m 个进程对 n 类资源仍需求资源

void showinventory(intn);//以数组形式显示出  资源的库存

void showall(int m, intn);//所有数据显示

bool IsNotSafe(int m,int n);//系统安全性检查,判断不安全

void ChangData(int n,int k);//申请资源数不超库存和需求,改变数据

void NotSafeBack(int n,int k);//判断不安全,将数据还回去

 

以及主程序intmain()

2.   背景知识

银行家算法是一个用来避免系统进入死锁状态的算法,用它可以判断系统的安全性,如果系统当前处于安全状态,则可以为申请资源的进程分配资源,如果不是安全状态,则不能为申请资源的进程分配资源。 

银行家算法执行过程中,首先判断申请资源的进程所申请的资源数目是否合法,若是合法的,则可以为其进行试分配,再利用安全性算法求出安全序列,·如果存在安全序列,则说明可以给申请资源的进程分配资源,分配成功,继续为其它进程服务。如果找不到安全序列,则说明为该进程分配资源后系统会进入不安全状态,所以不能为该进程分配资源,使该进程进入阻塞状态。若申请资源的进程申请的资源数目不合法,则不需要进行试分配,直接使其进入阻塞状态,处理其他申请资源的进程。 

3.   设计步骤与方法

3.1.  步骤1需求分析

3.1.1.   步骤1.1问题描述

当系统在进行资源管理时,如果对进程申请的资源分配不当,可能会使系统进入死锁状态,因而后面到来的进程也无法顺利执行。银行家算法中,要对当前申请资源的进程申请资源的数目进行判断,如果可以试分配,则试求出一个安全序列,如果可以求出,则说明给这个进程分配资源后系统不会进入不安全状态,将该进程申请的资源分配给他,若求不出安全序列,则说明将资源分配给该进程后系统会进入不安全状态,所以就使该进程进入阻塞状态,等待以后可以分配资源时再执行该进程,然后系统继续服务其它进程。通过这样一个过程,可以有效避免系统进入死锁状态。

3.1.2步骤1.2基本要求

(1)对各个进程的进程名,最大需求资源,已分配资源,系统可用资源等进行有序的输入。

 (2)对申请资源的进程要有合法性判断(如进程名,申请资源数等)。

(3)  若有进程申请资源,首先要对它申请的资源数进行判断。

(4)  在上面判断合法的前提下进行试分配,利用银行家算法求出安全序列,如果可以求出安全序列,则为该进程分配资源,询问是否继续输入,否则使它报错,退回已请求资源,询问是否继续输入。

3.1.3步骤1.3概要分析

在避免死锁的算法中,允许进程动态地申请资源,系统在进行资源分配之前,先计算资源分配的安全性。若此次分配不会使系统进入不安全状态,便将资源分配给该进程否则进程等待。

所谓安全状态是指系统能按某种顺序如<p1,p2,……,pn>(称<p1,p2,……,pn>为安全序列),就这样来为每个进程分配资源,直至最大需求。使每个进程都可以顺序地执行完毕。若系统不存在这样一个安全序列,那么系统此时会进入不安全状态。

虽然并非所有的不安全状态都会产生死锁状态,但当系统进入不安全状态后,便可能进而进入死锁状态;反之,只要系统处于安全状态,系统便可避免进入死锁状态。因此,避免死锁的实质在于,如何使系统不进入不安全状态,银行家算法就是用来判断某种情况会不会进入不安全状态。

3.2.  步骤2:设计

3.2.1步骤2.1:概要设计


3.2.2步骤2.2:详细设计

三个主要函数:1改变数据 2.判断不安全,将数据还回去3.判断安全性并找出安全序列

void ChangData(int n, int k);//申请资源数不超库存和需求,改变数据

{

       for(int j = 0; j < n; j++)

       {

              Inventory[j]= Inventory[j] - Request[j];//库存-请求

              Start[k][j]= Start[k][j] + Request[j];//现有+请求

              Need[k][j]= Need[k][j] - Request[j];//需求-请求

}

}

void NotSafeBack(int n, int k);//判断不安全,将数据还回去

{

       cout<<"正在退回资源"<<endl;

       for (int j = 0;j < n; j++)

       {

              Inventory[j]= Inventory[j] + Request[j];

              Start[k][j]= Start[k][j] - Request[j];

              Need[k][j]= Need[k][j] + Request[j];

 

       }

       cout<<"已退回资源"<<endl;

}

bool IsNotSafe(int m, int n);//系统安全性检查,判断不安全

int work[100];//n/表示剩下可供分配的有效资源数

       intfinish[100];//m表示第i个进程是否可以运行完

       inttemp[100];//mtemp[]用来记录进程安全执行的顺序

       int temp1 ;//标记为需要资源[j]小于剩余可分配有效资源[j]

       int i, j, k =0;

       int Reset=0 ;//判断是否要重循环

       for (i = 0; i< m; i++)//finish[]初始化为否

       {

              finish[i]= 0;

       }

       for (j = 0;j<n; j++)//初始化剩余可分配有效资源数为库存值

       {

              work[j]= Inventory[j];

       }

       for (i = 0;i<m; i++)//遍历进程看是否有刚好满足的

       {

              if(Reset==1)

              {

                     i= 0;//重头来过以免漏掉

              }

              Reset=0;

              temp1 =1;//标记为需要资源[j]小于剩余可分配有效资源[j]

              if (finish[i]== 1)continue;//已经分配过的跳掉

              for (j =0; j<n; j++)

              {//遍历资源i进程还需要的资源[j]是否大于剩余可分配有效资源[j]

                     if(Need[i][j]>work[j])

                     {

                            temp1= 0;

                            break;

                     }

              }

              if(finish[i] == 0 && temp1 == 1)//未分配过并且需要资源[j]小于剩余可分配有效资源[j]

              {//i进程还需要的资源[j]小于剩余可分配有效资源[j]

              //那么这个进程就可以执行完然后将资源归还系统

       //即可分配有效资源[j]=该进程全部现有资源[j]+原可分配有效资源[j]

                     for(j = 0; j<n; j++) //for1

                     {

                            work[j]= work[j] + Start[i][j];

                     }

                     finish[i]= 1;

                     temp[k]= i+1;//保存序列

                     k++;

                     Reset=1;

              }

             

       }

       for (i = 0;i<m; i++) //遍历下看看是否有安全序列

       {

              if(finish[i]==0)

              {

                     cout<< endl;

                     cout<< " 系统不安全!!! 本次资源申请不成功!!!"<< endl;

                     cout<< endl;

                     return1;

              }

       }

       //正确返回否值

       cout <<endl;

       cout <<" 经安全性检查,系统安全,本次分配成功。" << endl;

       cout <<endl;

       cout <<" 本次安全序列:";

       for (i = 0;i<m; i++)

       {

              cout<< "进程" << temp[i] ;

              if(i<m-1)cout<<"->";

              }

       cout <<endl << endl;;

       return 0;

}

4.   设计结果及分析

  


输入数据后经过安全性判断恰好能找到安全序列

5.   问题及心得体会

本来以为这个程序应该很简单很快就能好,结果实际操作起来却花了将近2周,虽然断断续续。使用的是好久没碰的c++,感觉特别是数组有点忘,就先看了几天《易学c++》温习一下。

       最开始我尝试了个简单版本的,就是以2维数组将一切包括进程数,资源类数,初始进程拥有资源,进程最大需求值先提前给出。然后用户只能输入请求的值。相对简易,大致为后来修改立下奠基。

   第一次修改将原来默认给定的数值全部改为动态输入的数据,以数组来存储,这就有了第二代版本,唯一缺点是我把初始进程拥有资源定义为0,这就大大增加了测试的麻烦程度,每次都得1个个数据申请判断,很烦因此推动我继续改进版本。

       第三代版本出现了,这一次,我将它更改为可输入进程数,资源类数,初始进程拥有资源,还可多次输出,并添加上最为核心的安全性判断法。然而,这一改变过程,却导致很多错误,导致一直卡在瓶颈,导致我一再几天没有进度。通过思考还有将每次变化数据显示出来,我很快发现了问题所在。

由于第二次版本的修改,我将初始进程拥有资源定义为0,因此当时的第m个进程还需要第n类资源的资源量Need值)可以看作是等于第m个进程对第n类资源最大资源需求量(MAX值),所以当时也没注意,才发现这个导致我测试频频饮恨的罪魁祸首;接着由于数组存在i[0],这与我们通俗叫法中的第一第二这种从一开始的相差了一位,导致常常出错,经过数据测试,我也及时通过+1-1来解决这个问题;然后判断安全性那里是我花了我最长时间的,总是搞不清楚哪里出错,其中一个就是缺乏对分配完成与未完成区别对待,导致多次将分配完的数据重复输入,后来设了一个finish[i]来标识是否完成分配同时循环开头用if语句判断是否跳过,缩短了时间;最后还是在安全性这里,经过多次数据测试发现,一些例题能成功找出正确的安全序列,有些却报错,再对那些报错和正确的数据断点观察后发现,原来由于i++的原因导致开始时第一个数被跳掉,因此添加判断标志Reset=0,来判断是否要重循环,是的话i=0,以免漏掉。以上都是我所遇到的典型错误,细小那些就不多提。

      经过这次课程设计,让我重新体会到编程的乐趣,那种专研后找到解决错误的快感,同时加深了我对银行家算法以及c++的了解,这次课程设计使我受益匪浅。

 

 源码

#include<iostream>
#include<iomanip>
#include<string>
using namespace std;
//int Start[5][4] = { { 0, 0, 3, 2 }, { 1, 0, 0, 0 }, { 1, 3, 5, 4 }, { 0, 3, 3, 2 }, { 0, 0, 1, 4 } };
int Start[100][100];//m个进程对n类资源初始拥有量 
int MAX[100][100];//m个进程对n类资源最大资源需求量 
int Need[100][100];//m个进程还需要n类资源的资源量 
int Inventory[100];//库存量
int Request[100];// 需要资源
void showstart(int m, int n);// 以数组形式显示出 m 个进程对 n 类资源已有资源
void showneed(int m, int n);// 以数组形式显示出 m 个进程对 n 类资源仍需求资源
void showinventory(int n);//以数组形式显示出  资源的库存
void showall(int m, int n);//所有数据显示

void ChangData(int n, int k);//申请资源数不超库存和需求,改变数据
void NotSafeBack(int n, int k);//判断不安全,将数据还回去
bool IsNotSafe(int m, int n);//系统安全性检查,判断不安全

int main()
{

	//初始化 m个进程对n类资源最大资源需求量 
	int m, n;//输入总进程数m和总资源类数n
	cout << "总进程数为:";
	cin >> m;
	cout << "总资源数类数:";
	cin >> n;
	//库存量输入
	for (int j = 0; j < n; j++)
	{
		cout << "第" << j + 1 << " 类总资源数为:";
		cin >> Inventory[j];
	}
	showinventory(n);

	//测试数据int MAX[4][3]={ { 8, 6, 7 }, { 6, 7, 8 }, { 4, 5, 2 }, { 4, 6, 3 } };

	for (int i = 0; i < m; i++)
	{

		for (int j = 0; j <n; j++)
		{
			cout << "第" << i + 1 << "个进程对第" << j + 1 << "类资源的最大需求量为:";
			cin >> MAX[i][j];
		}

		cout << endl;
	}

	//显示给客户看已输入的m个进程对n类资源最大资源需求量  以便下一步输入
	cout << "现在以数组形式显示出 " << m << " 个进程对 " << n << " 类资源最大资源需求量" << endl;
	for (int i = 0; i < m; i++)
	{
		cout << "{";
		for (int j = 0; j < n; j++)
		{
			cout << setw(2) << MAX[i][j];
			if (j<n - 1)cout << ",";
		}
		cout << "}" << endl;
	}

	//m个进程已经得到n类资源的资源量初始化
	cout << "请初始化各线程现有的资源" << endl;
	for (int i = 0; i < m; i++)
	{

		for (int j = 0; j <n; j++)
		{

			cout << "第" << i + 1 << "个进程已拥有的第" << j + 1 << "类资源数为:";
			cin >> Start[i][j];
			Need[i][j] = MAX[i][j] - Start[i][j];//需求量应当为最大值-初始拥有的
		}
		cout << endl;
	}

	showneed(m, n);
	cout << endl;
	showstart(m, n);

	//正式运行
	//int need[100][100];//m个进程还需要n类资源的资源量 
	//int request;// 需要资源
	char flag = 'y';
	while (flag == 'y' || flag == 'Y')//while1
	{
		//初始化请求资源
		for (int i = 0; i < n; i++)
		{
			Request[i] = 0;
		}
		int rj = -100;
		int  rl = -100;
		//第一步输入申请的进程号并判断是否合法
		while (rj <= 0 || rj >m) //while2
		{
			cout << " 请输入需要申请资源的进程号(从1到" << m << "!):";
			cin >> rj;
			if (rj <= 0 || rj >m)
			{
				cout << " 输入的进程号不存在,请重新输入!" << endl;
				continue;
			}

		} //end while2
		//
		//第二步输入要申请的资源
		for (int j = 0; j <n; j++)
		{

			rl = j;
			cout << "您希望为第 " << rj << " 进程申请多少 " << rl + 1 << "类资源:";
			cin >> Request[rl];
			//对申请资源数是否超库存和需求的判断
			if (Request[rl]>Inventory[rl])
			{
				cout << endl;
				cout << "您的请求无法完成,该" << rl << "类资源并没有那么多库存" << endl;
				cout << endl;
			}
			else if (Request[rl]>Need[rj - 1][rl])
			{
				cout << endl;
				cout << " 进程" << rj << "申请的资源数大于它还需要的" << rl << "类资源的资源量!";
				cout << "申请不合理,出错!请重新选择!" << endl << endl;
				cout << endl;
			}
		}
		ChangData(n, rj - 1);
	 	 
		if (IsNotSafe(m, n) == 1)
		{
			showall(m, n);
			//判断不安全,将数据还回去
			NotSafeBack(n, rj - 1);
			 

		}

		showall(m, n);
		//判断是否要继续
		cout << "请输入是否要继续申请资源(y / n)?" << endl;
		cin >> flag;
	}//end while1

}
//显示类函数
void showstart(int m, int n)
{

	cout << "现在以数组形式显示出 " << m << " 个进程对 " << n << " 类资源已有资源" << endl;
	for (int i = 0; i < m; i++)
	{
		cout << "{";
		for (int j = 0; j < n; j++)
		{
			cout << setw(2) << Start[i][j];
			if (j < n - 1)cout << ",";
		}
		cout << "}" << endl;
	}
}

//m个进程还需要n类资源的资源量 
void showneed(int m, int n)
{


	cout << "现在以数组形式显示出 " << m << " 个进程对 " << n << " 类资源仍所需资源" << endl;
	for (int i = 0; i < m; i++)
	{
		cout << "{";
		for (int j = 0; j < n; j++)
		{
			cout << setw(2) << Need[i][j];
			if (j < n - 1)cout << ",";
		}
		cout << "}" << endl;
	}
}
void showinventory(int n)
{
	/*
	for (int j = 0; j < n; j++)
	{

	cout << "第" << j +1<< " 类总资源数为:";
	cout << Inventory[j];
	cout << endl;

	}*/
	cout << "现在以数组形式显示出 " << n << " 类总资源数为:" << endl;
	cout << "{";
	for (int j = 0; j < n; j++)
	{
		cout << setw(2) << Inventory[j];
		if (j < n - 1)cout << ",";
	}
	cout << "}" << endl;


}
void showall(int m, int n)
{
	showstart(m, n);

	showneed(m, n);
	showinventory(n);
}
void ChangData(int n, int k)
{
	for (int j = 0; j < n; j++)
	{
		Inventory[j] = Inventory[j] - Request[j];//库存-请求
		Start[k][j] = Start[k][j] + Request[j];//现有+请求
		Need[k][j] = Need[k][j] - Request[j];//需求-请求

	}
}
void NotSafeBack(int n, int k)
{
	cout << "正在退回资源" << endl;
	for (int j = 0; j < n; j++)
	{
		Inventory[j] = Inventory[j] + Request[j];
		Start[k][j] = Start[k][j] - Request[j];
		Need[k][j] = Need[k][j] + Request[j];

	}
	cout << "已退回资源" << endl;
}

bool IsNotSafe(int m, int n)
{

	int work[100];//n/表示剩下可供分配的有效资源数
	int finish[100];//m表示第i个进程是否可以运行完
	int temp[100];//mtemp[]用来记录进程安全执行的顺序
	int temp1;//标记为需要资源[j]小于剩余可分配有效资源[j]
	int i, j, k = 0;
	int Reset = 0;//判断是否要重循环
	//finish[]初始化为否
	for (i = 0; i < m; i++)
	{
		finish[i] = 0;
	}
	//初始化剩余可分配有效资源数为库存值
	for (j = 0; j<n; j++)
	{
		work[j] = Inventory[j];
	}
	for (i = 0; i<m; i++)//遍历进程 看是否有刚好满足的
	{
		if (Reset == 1)
		{
			i = 0;//重头来过 以免漏掉
		}
		Reset = 0;
		temp1 = 1;//标记为需要资源[j]小于剩余可分配有效资源[j]
		if (finish[i] == 1)continue;//已经分配过的跳掉
		for (j = 0; j<n; j++)
		{

			//遍历资源 i进程还需要的资源[j]是否大于剩余可分配有效资源[j]
			if (Need[i][j]>work[j])
			{
				temp1 = 0;
				break;
			}

		}
		if (finish[i] == 0 && temp1 == 1)//未分配过并且需要资源[j]小于剩余可分配有效资源[j]
		{
			//i进程还需要的资源[j]小于剩余可分配有效资源[j]
			//那么这个进程就可以执行完 然后将资源归还系统
			//即可分配有效资源[j]=该进程全部现有资源[j]+原可分配有效资源[j]
			for (j = 0; j<n; j++) //for1
			{
				work[j] = work[j] + Start[i][j];
			}
			finish[i] = 1;
			temp[k] = i + 1;//保存序列
			k++;
			Reset = 1;
		}

	}

	for (i = 0; i<m; i++) //遍历下看看是否有安全序列
	{ 
		if (finish[i] == 0)
		{
			cout << endl;
			cout << " 系统不安全!!! 本次资源申请不成功!!!" << endl;
			cout << endl;
			return 1;
		}
	}
	//正确返回否值
	cout << endl;
	cout << " 经安全性检查,系统安全,本次分配成功。" << endl;
	cout << endl;
	cout << " 本次安全序列:";
	for (i = 0; i<m; i++)
	{
		cout << "进程" << temp[i];
		if (i<m - 1)cout << "->";
	}
	cout << endl << endl;;
	return 0;
}



  • 2
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值