操作系统中避免死锁的银行家算法【表面C++实际C语言】一学就废的菜鸡代码

文章目录

  • 银行家算法
  • 实验原理
    • 数据结构
    • 初始化
    • 输出资源分配量
    • 安全性算法
    • 银行家算法
  • 完整代码
  • 测试数据
  • 测试结果
    • 第一题
    • 第二题


银行家算法

银行家算法是一种最有代表性的避免死锁的算法。在避免死锁方法中允许进程动态地申请资源,但系统在进行资源分配之前,应先计算此次分配资源的安全性,若分配不会导致系统进入不安全状态,则分配,否则等待。(破坏了环路等待条件)


实验原理


数据结构

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]

int Allocation[11][101];//进程已获得资源
int Max[11][101];//进程所需最大资源
int Available[11];//可分配资源
int Need[11][101];//进程所需资源
int Requesti[11];//资源请求
int Work[11];//工作向量
int link[11];//安全序列
int x,y;//x表进程数,y表资源种类

初始化

帮助用户输入已知变量的函数,构建银行家算法的Max、Allocation、Need、Available矩阵,便于进行接下来的数据处理。

void init(){//初始化cout << "请输入进程个数:" << endl;cin >> x;cout << "请输入资源共有多少类:" << endl;cin >> y;cout << "请输入每个进程所需要的各种资源的最大数目:" << endl;for (int i = 0; i < x; i++) {cout << "P" << i+1 << ":" ;for (int j = 0; j < y; j++) {cin >> Max[i][j];}}cout << "请输入每个进程已分配的资源数量:" << endl;for(int i=0; i<x; i++){cout << "P" << i+1 << ":" ;for(int j=0; j<y; j++){cin >> Allocation[i][j];if(Allocation[i][j]>Max[i][j]){cout << "已分配资源数量大于进程所需的资源最大数目,请重新输入" << endl;i--;}}}cout << "请输入系统可分配的资源数:" << endl;for (int i = 0; i < y; i++) {cin >> Available[i];}for (int i = 0; i < x; i++) {//计算每一个进程尚需的各类资源数,Need矩阵for (int j = 0; j < y; j++) {Need[i][j] = Max[i][j] - Allocation[i][j];}}
}

输出资源分配量

打印现在的矩阵状态(Max、Allocation、Need、Available),方便用户了解算法进行程度

void printSystemVariable(){//输出资源分配量cout << "此时资源分配量如下:" << endl;cout << "进程  " << "   Max   " << "   Alloction " << "    Need  " << "    Available " << endl;for(int i=0;i<x;i++){//第i个进程cout << "P" << i+1 << "     " ;for(int j=0;j<y;j++){//第i个进程的Max矩阵信息cout << Max[i][j] << "    " ;}cout << "|  " ;for(int j=0;j<y;j++){//第i个进程的Allocation矩阵信息cout << Allocation[i][j] << "    " ;}cout << "|  " ;for(int j=0;j<y;j++){//第i个进程的Need矩阵信息cout << Need[i][j] << "    " ;}cout << "|  " ;if(i==0){for(int j=0;j<y;j++){//第i个进程的Available矩阵信息cout << Available[j] << "    " ;}}cout << endl ;}
}

安全性算法

1)设置两个向量:
工作向量Work: 它表示系统可提供给进程继续运行所需的各类资源数目,它含有m个元素,在执行安全算法开始时,Work=Available;
工作向量Finish: 它表示系统是否有足够的资源分配给进程,使之运行完成。开始时先做Finish[i]=false; 当有足够资源分配给进程时, 再令Finish[i]=true
2)从进程集合中找到一个能满足下述条件的进程:
Finish[i]=false;
Need[i,j]≤Work[j];
若找到,执行 (3),否则,执行 (4)
3)当进程Pi获得资源后,可顺利执行,直至完成,并释放出分配给它的资源,故应执行:
Work[j]=Work[i]+Allocation[i,j];
Finish[i]=true;
go to step 2;

4)如果所有进程的Finish[i]=true都满足, 则表示系统处于安全状态;否则,系统处于不安全状态

bool chesksafe(){//安全性算法for (int i = 0; i < y; i++) {Work[i] = Available[i];}bool Finish[7];//工作向量int mark = x;//避免改变x的值所设的变量int temp = 0;//满足需求资源少于剩余资源这一条件的资源数int flag = 0;//进行资源分配的次数while (mark--) {//求安全序列的操作最多进行进程数次for(int i=0;i<x;++i){//判定第i个进程if(Finish[i]==true){continue;}for (int j = 0; j < y; j++) {if(Need[i][j]<=Work[j]){//计算该进程需求资源少于剩余资源的资源数temp++;}}if(temp==y){//全部资源都满足需求资源少于剩余资源for (int j = 0; j < y; j++) {//获得分配给该资源的资源数Work[j]+=Allocation[i][j];}Finish[i]=true;flag++;//进行一次资源分配link[flag]=i+1;//将进行资源分配的进程依次放入队列}temp=0;//更新满足分配资源条件的资源数}}if(flag==x){//如果没有进行进程数次资源分配,说明不是安全序列cout << "系统处于安全状态,安全序列为:" << endl;for (int i = 1; i <= x; i++) {cout << "P" << link[i] << " " ;}cout << endl;return true;}else{cout << "系统处于不安全状态" << endl;return false;}
}

银行家算法

设Requesti是进程Pi的请求向量,如果Requesti[j]=K,表示进程Pi需要K个Rj类型的资源。当Pi发出资源请求后,系统按下述步骤进行检查:
(1)如果Requesti[j]≤Need[i,j],便转向步骤(2);否则认为出错,因为它所需要的资源数已超过它所宣布最大值。
(2)如果Requesti[j]≤Available[j],便转向步骤(3);否则,表示尚无足够资源,Pi须等待。
(3)系统试探着把资源分配给进程Pi,并修改下面数据结构中的数值:
Available[j]=Available[j]-Requesti[j];
Allocation[i,j]=Allocation[i,j]+Requesti[j];
Need[i,j]=Need[i,j]-Requesti[j];

系统执行安全性算法,检查此次资源分配后,系统是否处于安全状态。若安全,才正式将资源分配给进程Pi,以完成本次分配;否则,将本次的试探分配作废,恢复原来的资源分配状态,让进程Pi等待。

  string an;//存储是否请求分配的用户指令bool flag = false;//用于跳出两层循环的标志while(1){cout << "是否请求分配?('y'or'Y'表是,'n'or'N'表否) " ;cin>>an;if(an[0]!='Y'&&an[0]!='y'){break;}int num;cout << "请输入请求资源的进程号(如:P1则输入1): " << endl;cin >> num;num -= 1;//进程从1开始计数但各个数组下标从0开始计数cout << "输入进程请求的资源数" << endl;for (int i = 0; i < y; i++) {cin >> Requesti[i];}for (int i = 0; i < y; i++) {if(Requesti[i]>Need[num][i]){cout << "所需要的资源数已超过所宣布最大值Max" << endl;flag = true;break;}if(Requesti[i]>Available[i]){cout << "尚无足够资源" << endl;flag = true;break;}Available[i]-=Requesti[i];Allocation[num][i]+=Requesti[i];Need[num][i]-=Requesti[i];}if (flag){//当任意资源请求出现问题时,跳出两层循环flag = false;//更新标志continue;//执行下一次循环}int temp = 0;//满足Max值的Allocation值的个数if(chesksafe()){//安全,完成本次分配for (int i = 0; i < y; i++) {if(Allocation[num][i]>=Max[num][i]){temp++;}}if (temp == y) {/*如果1个进程分配资源后,每个资源已获得值都大于等于所需最大值则更新Available、Allocation和Need矩阵*/for (int i = 0; i < y; i++) {Available[i]+=Allocation[num][i];//可分配资源获得该进程已获得的资源数Allocation[num][i]=0;//清空该进程已获得的资源数Need[num][i]=0;//清空该进程尚需的各类资源数}}cout << "分配成功" << endl;printSystemVariable();}else{//不安全,撤销之前的操作cout << "分配失败" << endl;for (int i = 0; i < y; i++) {Available[i]+=Requesti[i];Need[num][i]+=Requesti[i];Allocation[num][i]-=Requesti[i];}printSystemVariable();}}

完整代码

#include <iostream>
using namespace std;int Allocation[11][101];//进程已获得资源
int Max[11][101];//进程所需最大资源
int Available[11];//可分配资源
int Need[11][101];//进程所需资源
int Requesti[11];//资源请求
int Work[11];//工作向量
int link[11];//安全序列
int x,y;//x表进程数,y表资源种类void init();//初始化
void printSystemVariable();//输出资源分配量
bool chesksafe();//安全性算法int main(int argc, char const *argv[]) {init();printSystemVariable();if(!chesksafe()){return 0;}string an;//存储是否请求分配的用户指令bool flag = false;//用于跳出两层循环的标志while(1){cout << "是否请求分配?('y'or'Y'表是,'n'or'N'表否) " ;cin>>an;if(an[0]!='Y'&&an[0]!='y'){break;}int num;cout << "请输入请求资源的进程号(如:P1则输入1): " << endl;cin >> num;num -= 1;//进程从1开始计数但各个数组下标从0开始计数cout << "输入进程请求的资源数" << endl;for (int i = 0; i < y; i++) {cin >> Requesti[i];}for (int i = 0; i < y; i++) {if(Requesti[i]>Need[num][i]){cout << "所需要的资源数已超过所宣布最大值Max" << endl;flag = true;break;}if(Requesti[i]>Available[i]){cout << "尚无足够资源" << endl;flag = true;break;}Available[i]-=Requesti[i];Allocation[num][i]+=Requesti[i];Need[num][i]-=Requesti[i];}if (flag){//当任意资源请求出现问题时,跳出两层循环flag = false;//更新标志continue;//执行下一次循环}int temp = 0;//满足Max值的Allocation值的个数if(chesksafe()){//安全,完成本次分配for (int i = 0; i < y; i++) {if(Allocation[num][i]>=Max[num][i]){temp++;}}if (temp == y) {/*如果1个进程分配资源后,每个资源已获得值都大于等于所需最大值则更新Available、Allocation和Need矩阵*/for (int i = 0; i < y; i++) {Available[i]+=Allocation[num][i];//可分配资源获得该进程已获得的资源数Allocation[num][i]=0;//清空该进程已获得的资源数Need[num][i]=0;//清空该进程尚需的各类资源数}}cout << "分配成功" << endl;printSystemVariable();}else{//不安全,撤销之前的操作cout << "分配失败,撤销本次操作" << endl;for (int i = 0; i < y; i++) {Available[i]+=Requesti[i];Need[num][i]+=Requesti[i];Allocation[num][i]-=Requesti[i];}printSystemVariable();}}return 0;
}void init(){//初始化cout << "请输入进程个数:" << endl;cin >> x;cout << "请输入资源共有多少类:" << endl;cin >> y;cout << "请输入每个进程所需要的各种资源的最大数目:" << endl;for (int i = 0; i < x; i++) {cout << "P" << i+1 << ":" ;for (int j = 0; j < y; j++) {cin >> Max[i][j];}}cout << "请输入每个进程已分配的资源数量:" << endl;for(int i=0; i<x; i++){cout << "P" << i+1 << ":" ;for(int j=0; j<y; j++){cin >> Allocation[i][j];if(Allocation[i][j]>Max[i][j]){cout << "已分配资源数量大于进程所需的资源最大数目,请重新输入" << endl;i--;}}}cout << "请输入系统可分配的资源数:" << endl;for (int i = 0; i < y; i++) {cin >> Available[i];}for (int i = 0; i < x; i++) {//计算每一个进程尚需的各类资源数,Need矩阵for (int j = 0; j < y; j++) {Need[i][j] = Max[i][j] - Allocation[i][j];}}
}void printSystemVariable(){//输出资源分配量cout << "此时资源分配量如下:" << endl;cout << "进程  " << "   Max   " << "   Alloction " << "    Need  " << "    Available " << endl;for(int i=0;i<x;i++){//第i个进程cout << "P" << i+1 << "     " ;for(int j=0;j<y;j++){//第i个进程的Max矩阵信息cout << Max[i][j] << "    " ;}cout << "|  " ;for(int j=0;j<y;j++){//第i个进程的Allocation矩阵信息cout << Allocation[i][j] << "    " ;}cout << "|  " ;for(int j=0;j<y;j++){//第i个进程的Need矩阵信息cout << Need[i][j] << "    " ;}cout << "|  " ;if(i==0){for(int j=0;j<y;j++){//第i个进程的Available矩阵信息cout << Available[j] << "    " ;}}cout << endl ;}
}bool chesksafe(){//安全性算法for (int i = 0; i < y; i++) {Work[i] = Available[i];}bool Finish[7];//工作向量int mark = x;//避免改变x的值所设的变量int temp = 0;//满足需求资源少于剩余资源这一条件的资源数int flag = 0;//进行资源分配的次数while (mark--) {//求安全序列的操作最多进行进程数次for(int i=0;i<x;++i){//判定第i个进程if(Finish[i]==true){continue;}for (int j = 0; j < y; j++) {if(Need[i][j]<=Work[j]){//计算该进程需求资源少于剩余资源的资源数temp++;}}if(temp==y){//全部资源都满足需求资源少于剩余资源for (int j = 0; j < y; j++) {//获得分配给该资源的资源数Work[j]+=Allocation[i][j];}Finish[i]=true;flag++;//进行一次资源分配link[flag]=i+1;//将进行资源分配的进程依次放入队列}temp=0;//更新满足分配资源条件的资源数}}if(flag==x){//如果没有进行进程数次资源分配,说明不是安全序列cout << "系统处于安全状态,安全序列为:" << endl;for (int i = 1; i <= x; i++) {cout << "P" << link[i] << " " ;}cout << endl;return true;}else{cout << "系统处于不安全状态" << endl;return false;}
}

测试数据

这里的测试数据就拿教材上的一个习题


测试结果

第一题

在这里插入图片描述

第二题

注意题中排序从0开始,程序排序从1开始,此题中的P2对应程序中的P3,输入数字应该是3而不是2

在这里插入图片描述
经演算结果完全正确√

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/443901.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

GitHub 使用指南

目录切换分支删除已有文件只删除远程仓库中的文件&#xff0c;不删除本地仓库中的文件同时删除远程仓库和本地仓库中的文件提交文件git查看本地分支连接的是哪个远程分支切换分支 查看本地和远程所有分支 git branch -a当前本地分支为绿色&#xff0c;当前所在分支前带有“*”号…

一学就废的并查集它来了

文章目录题目描述输入输出样例输入样例输出提示算法思想代码实现寻找根节点汇总连接情况完整代码关于flag的初值题目描述 某省调查城镇交通状况&#xff0c;得到现有城镇道路统计表&#xff0c;表中列出了每条道路直接连通的城镇。省政府“畅通工程”的目标是使全省任何两个城…

百战c++(2)

delete 和 delete []的真正区别 delete 对应 new delete[]对应new[]对于简单类型包括简单类型数组&#xff0c;delete 与delete[]没有区别。对于自定义类型数组&#xff0c;delete 只会删除一个元素&#xff0c;delete 则会删除所有元素。 指针和数组的区别 野指针是什么 野指…

Linux实验一:常用的Linux命令

文章目录一、实验目的二、实验要求三、实验内容1、系统的使用2、命令的使用3、文件操作4、系统询问与权限口令5、其它常用命令四、实验操作1、基本命令的使用2、文件和目录操作3、创建用户帐户一、实验目的 1、熟悉Linux的桌面环境&#xff1b; 2、了解Linux所安装的软件包 3、…

Linux实验二:vi编辑器的使用

文章目录一、实验目的二、实验要求三、实验内容1、创建文件2、编辑文件一、实验目的 1、练习并掌握Linux提供的vi编辑器来编译C程序 2、学会利用gcc、gdb编译、调试C程序 3、本次实验的目的是让同学们了解如何使用vi编辑器进行创建和编辑文件 二、实验要求 1、文件编辑器vi…

百战c++(os1)

Linux中的锁 互斥锁&#xff1a;mutex&#xff0c;用于保证在任何时刻&#xff0c;都只能有一个线程访问该对象。当获取锁操作失败时&#xff0c;线程会进入睡眠&#xff0c;等待锁释放时被唤醒 读写锁&#xff1a;rwlock&#xff0c;分为读锁和写锁。处于读操作时&#xff0…

Linux实验三:Shell编程

文章目录一、实验目的二、实验要求三、实验内容1、通配符的使用2、重定向3、管道4、shell变量5、建立下面的脚本&#xff0c;运行并分析输出结果&#xff0c;并给出代码注释。6、编写脚本一、实验目的 1.为文件扩展名使用通配符 2.标准输入、标准输出和标准错误的重定向 3.使…

Linux实验四:编译和调试工具的使用

文章目录一、实验目的&#xff1a;二、实验要求三、实验内容四、实验操作1、用gcc编译程序&#xff0c;写出编译过程&#xff0c;并给出运行结果。2、调试程序&#xff0c;要求用gdb进行调试并给出修改方案。3、make的使用一、实验目的&#xff1a; 1、练习并掌握Linux提供的v…

Linux实验五:Linux环境下的C语言编程

文章目录一、实验目的&#xff1a;二、实验要求三、实验内容1、编写一段C语言程序使其完成&#xff1a;父进程创建两个子进程&#xff0c;每个进程都在屏幕上显示自己的进程ID号。2、上机调试下面的程序&#xff0c;观察运行结果&#xff0c;分析原因。3、利用两个管道进行双向…

ndarray对象的建立

文章目录ndarray&#xff08;别名array&#xff09;常用属性创建NumPy数组使用array()函数使用zeros()函数使用ones()函数使用empty()函数使用arange()函数注意ndarray&#xff08;别名array&#xff09; 常用属性 import numpy as np # Numpy工具包data np.arange(12).res…

Numpy数组的广播机制

文章目录前言数组广播广播机制的使用条件前言 Numpy数组不需要循环遍历&#xff0c;即可对每个元素执行批量的算术运算操作&#xff08;矢量化运算&#xff09;。当两个数组大小&#xff08;Numpy.shape&#xff09;不同时&#xff0c;进行算术运算会出现广播机制。 数组广播…

数组的转置和轴对称

文章目录T属性transpose()方法swapaxes()方法T属性 import numpy as np # Numpy工具包data np.arange(12).reshape(3, 4) # 创建一个3行4列的数组 print(data)# 数组的转置和轴对称 data1 data.T print(data1)print(data) [[ 0 1 2 3] [ 4 5 6 7] [ 8 9 10 11]] print(dat…

管道实现父子进程的信息传递(一)【fork函数、pipe函数、write/read操作、wait函数】

文章目录题目描述代码实现关于pipe函数关于读写操作关于读写端口关于wait函数功能&#xff1a;注意&#xff1a;关于fork函数题目描述 编写一个程序&#xff0c;利用管道实现父子进程的通信&#xff0c;父进程向子进程发送信息&#xff0c;由子进程输出显示。 代码实现 #inclu…

基础的shell编程问题(一)

文章目录题目一题目描述代码实现关于$#的有关内容实测本程序的作用题目二题目描述代码实现注释关于argc、argv关于read函数关于文件描述符关于write函数本程序的作用题目三题目描述代码实现实测关于grep命令关于read命令题目四题目描述代码实现关于test命令实测题目一 题目描述…

基础的shell编程问题(二)

文章目录题目一题目描述代码实现结果验证关于本题题目二题目描述代码实现结果测试题目三题目描述代码实现及结果测试题目四题目描述代码实现及结果测试题目五题目描述代码实现及结果测试题目一 题目描述 输入的命令行参数必须是hello&#xff0c;才会正确显示&#xff1b;否则…

Numpy实现酒鬼漫步问题【以及randint()、where()、cumsum()、argmax()的用法详解】

文章目录题目描述代码实现关于本题涉及到的几个函数randint()where()cumsum()题目拓展题目描述代码实现题目拓展题目描述代码实现argmax()题目描述 从前有一个酒鬼&#xff0c;喝醉了行走在一条直线上&#xff0c;每走一步方向是不确定的&#xff08;向前或者向后&#xff09;…

搞清axis的含义,这一篇就够了!

文章目录axis的含义旁门左道式理解二维数组中的axis三维数组中的axis正规理解axis的含义 在自己分析之前先摆上官方关于多维数组中axis的值的定义&#xff1a; axis 0&#xff0c;表示第一个维度 axis 1&#xff0c;表示第二个维度 axis -1&#xff0c;表示最后一个维度…

Struts2.3.5+Hibernate3+Spring3.1基于注解实现的多文件上传,下载

Struts2.3.5Hibernate3Spring3.1基于注解实现的的多文件上传&#xff0c;下载,这里是上传文件到数据库中&#xff0c;上传控件可以增加和删除&#xff0c;有需要的朋友可以看看。 以下是源码下载地址&#xff1a;http://www.zuidaima.com/share/1639672872438784.htm jar包的下…

【精品计划1】动态规划入门到熟悉,看不懂来打我啊

持续更新。。。。。。 2.1斐波那契系列问题 2.2矩阵系列问题 2.3跳跃系列问题 3.1 01背包 3.2 完全背包 3.3多重背包 3.4 一些变形选讲 2.1斐波那契系列问题 在数学上&#xff0c;斐波纳契数列以如下被以递归的方法定义&#xff1a;F(0)0&#xff0c;F(1)1, F(n)F(n-1)…

【大总结2】大学两年,写了这篇几十万字的干货总结

本文是我大学两年知识的总结。涵盖数据结构、算法、语言基础、操作系统、关系数据库、NOSQL、网络/前端/项目基础知识、安全和测试、框架的学习、中间件和工具、设计模式和框架原理、我推荐的资料、我的建议 本篇文章应该算是Java后端开发技术栈的&#xff0c;但是大部分是基础…