操作系统之进程调度——优先权法和轮转法(附上样例讲解)
操作系统之银行家算法—详解流程及案例数据
操作系统之多线程编程—读者优先/写者优先详解
操作系统之存储管理——FIFO算法和LRU算法
操作系统之磁盘调度——SCAN实例讲解

要求

银行家是操作系统比较经典的算法之一,他比较好的防止死锁情况的出现,增加了系统的安全性.在编写银行家算法的过程中,对操作系统的银行家算法有了深入了解和心得。

一、实验目的
死锁会引起计算机工作僵死,因此操作系统中必须防止。本实验的目的在于让学生独立的使用高级语言编写和调试一个系统动态分配资源的简单模拟程序,了解死锁产生的条件和原因,并采用银行家算法有效地防止死锁的发生,以加深对课堂上所讲授的知识的理解。
二、实验要求
设计有n个进程共享m个系统资源的系统,进程可动态的申请和释放资源,系统按各进程的申请动态的分配资源。
系统能显示各个进程申请和释放资源,以及系统动态分配资源的过程,便于用户观察和分析;
三、数据结构
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。Allocation i表示进程i的分配向量,有矩阵Allocation的第i行构成。
4.需求矩阵Need,这是一个n×m的矩阵,用以表示每个进程还需要的各类资源的数目。如果Need(i,j)=k,表示进程i还需要Rj类资源k个,才能完成其任务。Need i表示进程i的需求向量,由矩阵Need的第i行构成。
上述三个矩阵间存在关系:Need(i,j)=Max(i,j)-Allocation(i,j);
四、安全性算法
1.设置两个向量。
Work:它表示系统可提供给进程继续运行的各类资源数目,它包含m个元素,开始执行安全性算法时,Work = Available。
Finish:它表示系统是否有足够的资源分配给进程,使之运行完成,开始Finish(I)=false;当有足够资源分配给进程Pi时,令Finish(i)=true;
2.从进程集合中找到一个能满足下述条件的进程。
Finish(i)= = false;
Need i ≤work;
如找到则执行步骤3;否则,执行步骤4;
3.当进程Pi获得资源后,可顺利执行直到完成,并释放出分配给它的资源,故应执行
Work = work Allocation i
Finish(i)=true;转向步骤2;
4.若所有进程的Finish(i)都为true,则表示系统处于安全状态;否则,系统处于不安全状态。

流程图:

个人觉得。总的来说,银行家算法就是一个模拟借钱。判断假如借钱是否安全然后考虑借不借的问题。
先放代码,和数据再说分析:

代码

import java.util.ArrayDeque;
import java.util.Queue;
import java.util.Scanner;
public class bank {static Scanner sc=new Scanner(System.in);static int n;static int m;static int available[];static int max[][];//最大需求矩阵static int allocation[][];//当前分配到每一个进程的static int need[][];//需求矩阵static boolean isrelesed[];//资源是否已经释放public static void main(String[] args) {// TODO 自动生成的方法存根        System.out.println("请输入资源种类m:");m=sc.nextInt();//系统资源initm(m);//初始相关System.out.println("输入进程数量");n=sc.nextInt();//进程数量initn(n);//初始相关矩阵//getstatus();//输出当前状态while(true) {applyresouse();//申请资源}}static void applyresouse()//申请资源{getstatus();//输出状态int request[]=new int[m];//需求量 为了节省空间写成全部变量System.out.println("输入你想申请资源的编号");int index=sc.nextInt();while(0>index||index>=n) {System.out.println("输入的编号不在编号范围之内,请重新输入");index=sc.nextInt();   }while(isrelesed[index]) {System.out.println("改编号已经完成资源的释放,无法再请求资源,请重新输入");index=sc.nextInt();while(0>index||index>=n) {System.out.println("输入的编号不在编号范围之内,请重新输入");index=sc.nextInt(); }}System.out.println("请输入"+m+"个资源申请的个数(不申请的资源用0替代)");int team=0;while(team==0) {for(int i=0;i<m;i++){request[i]=sc.nextInt();if(request[i]>available[i]) {team=1;}if(request[i]>max[index][i]) {team=2;}}if(team==1) {System.out.println("您的请求量超出 了系统提供量,请重新输入");team=0;}//重新循环else if(team==2) {System.out.println("您的请求量超出 了最大请求量max,请重新输入");team=0;}else team=3;//退出循环用}//赋值成功后开始boolean isfinish= ifallocate(index,request);if(isfinish) {System.out.println("所有进程完成资源分配,分配结束");System.exit(0);}}  private static boolean ifallocate(int index,int[] request) {//假设分配/** 首先要将真的数组克隆,模拟已经给资源,然后判断这个资源是否安全*/int work[]=available.clone();boolean finish[]=isrelesed.clone();//克隆初始状态int need2[][]=new int[n][m];int allocate2[][]=new int[n][m];for(int i=0;i<n;i++){need2[i]=need[i].clone();allocate2[i]=allocation[i].clone();}for(int i=0;i<m;i++){if(need[index][i]<request[i])request[i]=need[index][i];//可以借这么多钱但是我不需要这么多钱anwork[i]-=request[i];//假设把钱借出去allocate2[index][i]+=request[i];}//需要把need2重置一下for(int i=0;i<m;i++){need2[index][i]-=request[i];}boolean isallocate=issafety(work, finish, need2, allocate2);if(!isallocate) {System.out.println("分配造成进程不安全,取消分配"); return false;}else {System.out.println("分配成功");//分配成功就要分配资源for(int i=0;i<m;i++){available[i]-=request[i];allocation[index][i]+=request[i];need[index][i]-=request[i];//System.out.println(request[i]);}if(!isrelesed[index])//判断改资源是否释放{boolean jud=false;for(int j=0;j<m;j++){if(need[index][j]!=0)jud=true;}if(!jud)//资源需要释放 {isrelesed[index]=true;for(int j=0;j<m;j++){available[j]+=allocation[index][j];}}}     }boolean isfinished=true;for(int i=0;i<n;i++){for(int j=0;j<m;j++) {if(need[i][j]!=0) {isfinished=false;return false;}}}return isfinished;}private static boolean issafety(int work[],boolean finish[],int need2[][],int allocate2[][])//模拟的需求和分配{//int work[]=available.clone();//不能直接等于复制。可以了解下对象克隆或者深浅复制。Queue<Integer>q1=new ArrayDeque<Integer>();//如果能完成的队列int time=0;while(true){boolean loop=true;for(int i=0;i<n;i++)//n个进程模拟{time++;if(!finish[i]) {boolean b=false;//完成不了的for(int j=0;j<m;j++){if(work[j]<need2[i][j]){b=true;//完成不了的}if(b) {break;}}if(!b) {//可以完成的,释放资源time=0;//重新计数q1.add(i);finish[i]=true;//已经完成for(int j=0;j<m;j++){work[j]+=allocate2[i][j];//allocate2[i][j]+=need2[i][j];need2[i][j]=0;}//打印System.out.print("进程"+i+" max:");for(int j=0;j<m;j++){System.out.print(max[i][j]+" ");}System.out.print("allocate2: ");for(int j=0;j<m;j++){System.out.print(allocate2[i][j]+" ");}System.out.print("need2: ");for(int j=0;j<m;j++){System.out.print(need2[i][j]+" ");}System.out.print("work: ");for(int j=0;j<m;j++){System.out.print(work[j]+" ");}System.out.println();}}}boolean isfinish=false;for(int i=0;i<n;i++) {if(!finish[i]) {isfinish=true;break;}}if(!isfinish) {return true;}if(time>n) {return false;}}//return false;}static void initm(int m){System.out.println("请输入"+m+"种资源的最大量");available=new int[m];isrelesed=new boolean[m];//request=new int[m];for(int i=0;i<m;i++)//初始aviliable{available[i]=sc.nextInt();}}static void initn(int n){max=new int[n][m];allocation=new int[n][m];need=new int[n][m];//finish=new boolean[n];for(int i=0;i<n;i++){System.out.println("进程"+i+"的最大需求为:(输入m个数)");boolean jud=false;//判断输出是否有误for(int j=0;j<m;j++){max[i][j]=sc.nextInt();if(max[i][j]>available[j]) {jud=true;}}if(jud) {System.out.println("最大需求输入有误,请重新赋值(m个数)");i--;}//i自减满足条件}System.out.println("n个线程m种资源最大需求赋值完成\n请输入当前进程已分配资源情况");//初始maxfor(int i=0;i<n;i++)//初始allocate矩阵{System.out.println("进程"+i+"已分配资源为:(输入m个数)");boolean jud=false;for(int j=0;j<m;j++){allocation[i][j]=sc.nextInt();if(allocation[i][j]>max[i][j]){jud=true;}}if(jud) {System.out.println("输入有误,请重新输入");i--;}//输入有错误}System.out.println("allocate(当前已分配矩阵已经分配完毕)");}static void getstatus()//输出状态{for(int i=0;i<n;i++){for(int j=0;j<m;j++){need[i][j]=max[i][j]-allocation[i][j];}}for(int i=0;i<n;i++){System.out.print("进程"+i+"的状态为:max: ");for(int j=0;j<m;j++) {System.out.print(" "+max[i][j]+" ");}System.out.print("allocatem: ");for(int j=0;j<m;j++) {System.out.print(" "+allocation[i][j]+" ");}System.out.print("need: ");for(int j=0;j<m;j++) {System.out.print(" "+need[i][j]+" ");}System.out.print("avaliable: ");for(int j=0;j<m;j++) {System.out.print(" "+available[j]+" ");}System.out.println();}}
}

分析

A还—>借B—>B还—>C—这样可以到最后。但是很多情况下客户是分期借的,这就要考虑安全性问题,比如A借6,6,6还剩4,4,4那么这个银行做多最多只能借2,2,2给其他人,因为一旦借多了A也无法释放,那么就造成死锁。那么这种情况就不能够借钱。所以在借钱的时候需要一个模拟的过程。

  • 还有比较重要的是明白银行加算法各个矩阵的意义和作用非常的重要,我刚开始看银行家算法的时候因为对一些基础概念和数组矩阵的属性不够了解,茫然了很久,也走了很多的坑。那么就先介绍一下吧。
  • 对于全局变量,我的代码中有:
  • 这些变量是在安全状态下的真实变量其中:
  • (1)n是线程的数量,m是资源的种类。
  • Available[]是当前还可以使用的资源。也就是银行家手中被借出去钱,手中还剩余各种钱的数量。只跟资源有关
  • Max[][]是最大需求矩阵,也可以理解为最终终态矩阵,因为这个max的状态就是客户想达到和满足的状态。也就是线程可以释放的状态。
  • Allocate[][]是已分配矩阵。就是客户已经借到的钱。也就是线程已经占有的资源量
  • Need[][]是还需要资源情况,由max和allcate决定。
  • Isrelese[]这个数组和线程有关和资源无关,它记录的就是线程是否达到终态,完成资源释放的情况,,一旦完成借钱就不需要借钱。
  • 3:最后在具体实现的过程中。由于需要模拟过程,还是会遇到挺多坎的,在理清思路之后。在代码上还是由挺多要注意的。
    第一:对象克隆(深浅拷贝),在模拟的过程中拥有初始化和真实数据一样的数组。但是如果直接赋值那么新对象指向的还是老数组的地址,会造成数据紊乱。那么对象克隆就一定要保证只赋值数据,不复制地址。
    第二:模拟数值的改变,无论在申请资源,还是释放资源的时候,模拟的数值都会改变。但是不过如果模拟成功,真实数组会增加多少。这个需要尤其注意,同时,如果发现数值和预期不符合可以打断点单步调试。

附上我自己的流程图:
初始化:

借钱:

ps:本人有点菜,这里面可能有挺多的是错误的。。如果有大佬发现请指正。

如果对后端、爬虫、数据结构算法等感性趣欢迎关注我的个人公众号交流:bigsai

操作系统之银行家算法—详解流程及案例数据相关推荐

  1. 计算机操作系统——银行家算法详解(C语言版)

    目录 一.实验目的 二.实验内容 三.实验要点说明 数据结构 银行家算法bank()函数 安全性算法safe()函数 银行家算法实例 程序结构 四.实验代码 五.结果展示 一.实验目的 通过编写一个模 ...

  2. 操作系统之死锁的避免-银行家算法详解

    1.银行家算法中的数据结构   (1) 可利用资源向量Available.这是一个含有m个元素的数组,其中的每一个元素代表一类可利用的资源数目,其初始值是系统中所配置的该类全部可用资源的数目,其数值随 ...

  3. 银行家算法( 详解 )

    文章目录 一.什么是银行家算法? 二.银行家算法中的数据结构 三.流程图 四.代码实现 一.什么是银行家算法? 银行家算法是操作系统的经典算法之一,用于避免死锁情况的出现. 它最初是为银行设计的(因此 ...

  4. [OS] 死锁相关知识点以及银行家算法详解

    因此我们先来介绍一下死锁: 死锁特征 当出现死锁时,进程永远不能完成,并且系统资源被阻碍使用,阻止了其他作业开始执行.在讨论处理死锁问题的各种方法之前,先深入讨论一下死锁的特征. ·必要条件 (1)互 ...

  5. 操作系统:FIFO算法详解及代码演示

    FIFO算法 FIFO算法是最简单的页面置换算法.FIFO算法为每个页面记录了调到内存的时间.当必须置换页面的时候,选择最旧的页面. 通俗来说,每次进入主存的时候 如果主存中不存在这个页面,那么最先进 ...

  6. 目标检测 RCNN算法详解

    原文:http://blog.csdn.net/shenxiaolu1984/article/details/51066975 [目标检测]RCNN算法详解 Girshick, Ross, et al ...

  7. FloodFill算法详解及应用

    FloodFill算法详解及应用 啥是 FloodFill 算法呢, 最直接的一个应用就是「颜色填充」,就是 Windows 绘画本中那个小油漆桶的标志,可以把一块被圈起来的区域全部染色. 这种算法思 ...

  8. c4.5算法 程序语言,决策树之C4.5算法详解-Go语言中文社区

    决策树之C4.5算法详解 主要内容 C4.5算法简介 分裂属性的选择--信息增益率 连续型属性的离散化处理 剪枝--PEP(Pessimistic Error Pruning)剪枝法 缺失属性值的处理 ...

  9. 计算机操作系统实验银行家算法,实验六 银行家算法(下)

    实验六 银行家算法(下) 一.实验说明 实验说明:本次实验主要是对银行家算法进行进一步的实践学习,掌握银行家算法的整体流程,理解程序测试时每一步的当前状态,能对当前的资源分配进行预判断. 二.实验要求 ...

最新文章

  1. 设计师之歌 --【死了都要改】
  2. 服务器网站数据用什么方式加以保留?
  3. Java学习小程序(5)猜数字游戏
  4. .NET5发布了,腾讯招聘点名要求精通MySQL,而不是SQLServer!
  5. python和ui设计,PySide2相当于PyQt5的loadUiType(),用于在UI设计中动态混合
  6. ES6函数相关包含箭头函数
  7. 在Sping Boot logback的使用
  8. SQL解析和优化器获得重大思路进展
  9. Android对话框动态加载布局
  10. ios 视图切换翻页效果
  11. PDF、WORD文档快速翻译成中文的方法,帮你一键搞定!
  12. 基于短时时域处理中短时能量和过零率的语音端点检测方法
  13. 【开源】技术宅硬核跨年,DIY墨水屏日历:自动刷新位置、天气,随机播放2000多条「毒鸡汤」...
  14. 使用node加密excel文件
  15. Codeforces - Reachable Strings
  16. 别混淆区别很大 LED网格屏和格栅屏区别对比及分析
  17. 二级干线熔接机选什么好?TFN FT-3 二级干线专用光纤熔接机
  18. 德克萨斯长角牛 --最短路径
  19. 【自然语言处理】ChatGPT 相关核心算法
  20. 一个简单的安居客房屋信息爬虫

热门文章

  1. 【Opencv实战】简易版“美颜”来啦—再见旧照片,Python一键美颜哦~
  2. [Java基础]Map集合的遍历
  3. ATF RT-SVC的介绍
  4. 序列密码体制——密码学笔记(三)
  5. 使用gotoxy()函数移动控制台光标
  6. 微信小程序开发(二)
  7. 【安全漏洞】Struts2漏洞集合总结
  8. 攻击者怎样使用HTML和CSS隐藏“外部发件人”电子邮件警告
  9. python获取IP位置信息
  10. connection could not be established with host smtp.exmail.qq.com