-
概述:
- 银行家算法是操作系统领域中用于避免死锁的经典算法
- 其核心思想是通过模拟资源分配的过程,系统在进行资源分配之前,应先计算此次分分配资源的安全性,若分配不会导致系统进入不安全状态,则分配,否则等待
- 实现银行家算法,系统必须设置若干数据结构
-
死锁(Deadlock):
- 是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去
- 称此时系统处于死锁状态或系统产生了死锁
- 称这些永远在互相等待的进程成为死进程
-
资源与进程:
- 在操作系统中,资源是有限的,而多个进程会竞争这些资源
- 银行家算法通过以下关键数据结构来描述资源分配的状态:
- 资源向量(Available):表示系统中当前可用的每种资源的数量
- 最大需求矩阵(Max):记录每个进程对每种资源的最大需求量
- 分配矩阵(Allocation):表示当前已分配给每个进程的资源数量
- 需求矩阵(Need):表示每个进程还需要的资源数量,计算公式为:Need = Max - Allocation
-
安全状态:
- 银行家算法的核心目标是确保系统始终处于 "安全状态"
- 所谓安全状态,是指在一种资源分配顺序,使得所有进程都能顺利完成,而不会导致死锁
- 系统需要满足以下条件:
- 每个进程的资源请求不超过其最大需求
- 系统能够找到一个安全序列,使得每个进程都能获得所需资源并完成执行
-
不安全状态:
- 不存在一个安全序列。不安全状态不一定导致死锁
-
工作流程:
-
初始化:
- 在算法开始前,需要初始化以下数据结构:
- Need:每个进程还需要的资源数量
- Allocation:当前已分配给每个进程的资源数量
- Max:每个进程的最大资源需求
- Available:系统当前可用的资源数量
- 在算法开始前,需要初始化以下数据结构:
-
资源请求处理:
-
当一个进程请求资源时,系统会执行以下步骤:
- 检查请求合法性:如果请求的资源数量超过进程的最大进程需求,请求将被拒绝
- 检查资源可用性:如果请求的资源数量超过系统当前可用资源,进程需要等待
- 试探性分配:假设分配资源,并跟新 Available、Allocation 和 Need 矩阵
- 安全性检查:检查系统是否仍处于安全状态
- 如果是,则正式分配资源
- 否则,撤销试探性分配
-
-
安全性检查:
- 安全性检查是银行家算法的核心步骤,其目的是找到一个安全序列,步骤如下:
- 初始化工作项量 Work 和完成标志 Finish
- 查找一个未完成的进程,其资源需求小于等于 Work
- 如果找到这样的进程,假设其可以完成,并释放其占用的资源
- 重复上述步骤,直到所有进程都完成或无法找到满足条件的进程
- 安全性检查是银行家算法的核心步骤,其目的是找到一个安全序列,步骤如下:
-
-
实现银行家算法:
-
定义全局变量:
private static final int W = 10,R = 10; int M,N; //总进程数、资源种类 int[] ALL_RESOURCE = new int[W]; //默认各种资源总数目为 10 种 int[][] MAX = new int[W][R]; // M 个进程对 N 类资源最大资源需求量 int[] AVAILABLE = new int[R]; //系统可用资源数 int[][] ALLOCATION = new int[W][R]; // M 个进程已经得到 N 类资源的资源量 int[][] NEED = new int[W][R]; int[] Request = new int[W]; int[] P = new int[W]; //进程安全序列 String fileName = "D:\\data.txt";
-
txt 文件需要的数据():
3 2 10 5 7 5 3 2 6 3 2 1 1 1 2 1
-
构造器:
public BankerAlgorithm() throws FileNotFoundException { System.out.println("\t 银行家算法"); System.out.println("-------------------"); Scanner sc = new Scanner(new FileReader(fileName)); System.out.println("请输入总进程数:"); M = sc.nextInt(); System.out.println("总进程数为:" + M); System.out.println("-------------------"); System.out.println("请输入总资源种类:"); N = sc.nextInt(); System.out.println("请输入总资源种类:" + N); System.out.println("-------------------"); System.out.println("请输入各类资源总数:(需要输入为" + N + "个)"); for (int i = 0; i < N; i++) { ALL_RESOURCE[i] = sc.nextInt(); System.out.println("各种资源总数为:" + ALL_RESOURCE[i] + " "); } System.out.println("-------------------"); System.out.println("输入各进程所需最大的各类资源的数量:(需要输入数为:" + M * N + "个)"); for (int i = 0; i < M; i++) { for (int j = 0; j < N; j++) { do { MAX[i][j] = sc.nextInt(); if(MAX[i][j] > ALL_RESOURCE[j]) System.out.println("占有资源超过了声明的该资源总量,请重新输入"); }while (MAX[i][j] > ALL_RESOURCE[j]); System.out.println("各进程所需最大的各类资源的数量为:" + MAX[i][j]); } System.out.println(); } System.out.println("--------------------"); System.out.println("请输入各进程已经占据的各类资源的数量:(需要输入为" + M * N + "个)"); for (int i = 0; i < M; i++) { for (int j = 0; j < N; j++) { do { ALLOCATION[i][j] = sc.nextInt(); if(ALLOCATION[i][j] > MAX[i][j]){ System.out.println("占有资源超过了声明的最大资源,请重新输入"); } }while (ALLOCATION[i][j] > MAX[i][j]); System.out.println("各进程已经占据的各类资源的数量为:" + ALLOCATION[i][j]); } System.out.println(); } //初始化资源数量 int p; for (int i = 0; i < N; i++) { p = ALL_RESOURCE[i]; for (int j = 0; j < M; j++) { p = p - ALLOCATION[j][i]; //减去已经被占用的资源 AVAILABLE[i] = p; if(AVAILABLE[i] < 0){ AVAILABLE[i] = 0; } } } for (int i = 0; i < M; i++) { for (int j = 0; j < N; j++) { NEED[i][j] = MAX[i][j] - ALLOCATION[i][j]; } output(); bank(); } }
-
输出:
//输出资源信息 public void output(){ int i,j; System.out.println("--------------------"); System.out.println("各种资源的总数量为:"); for ( j = 0; j < N; j++) { System.out.print(" 资源" + j + ": " + ALL_RESOURCE[j]); } System.out.println("\n--------------------"); System.out.println("目前各种资源可利用的数量为:"); for (j = 0;j < N;j++){ System.out.print(" 资源" + j + ":" + AVAILABLE[j]); } System.out.println("\n--------------------"); System.out.println("各进程还需要的资源数量: "); for (i = 0;i<N;i++){ System.out.print("资源 " + i + " \t"); } System.out.println(); for (i = 0;i<M;i++){ System.out.print("进程 " + i + " \t"); for (j=0;j<N;j++){ System.out.print(NEED[i][j] + "\t\t"); } System.out.println(); } System.out.println("\n--------------------"); System.out.println("各进程已经得到的资源数量: "); for (i = 0;i < N;i++){ System.out.print("资源 " + i + " \t"); } System.out.println(); for (i = 0;i < M;i++){ System.out.print("进程 " + i + " \t"); for (j = 0;j < N;j++){ System.out.print(ALLOCATION[i][j] + "\t\t"); } System.out.println(); } System.out.println(); }
资源分配与回收:
//进行资源分配 public void distribute(int k){ for (int j = 0; j < N; j++) { AVAILABLE[j] -= Request[j]; ALLOCATION[k][j] += Request[j]; NEED[k][j] -= Request[j]; } } //进行资源回收 public void restore(int k){ for (int i = 0; i < N; i++) { AVAILABLE[i] += Request[i]; ALLOCATION[k][i] -= Request[i]; NEED[k][i] += Request[i]; } }
-
安全性检查:
//安全性检查 public boolean check(){ int[] WORK = new int[R],FINISH = new int[W]; for (int i = 0; i < N; i++) { WORK[i] = AVAILABLE[i]; } for (int j = 0; j < M; j++) { FINISH[j] = 0; } int j; int l = 0; for (int i = 0; i < M; i++) { if(FINISH[i] == 1) continue; else { for ( j = 0; j < N; j++) { if(NEED[i][j] > WORK[j]) break; } if (j == N){ //说明该行的 need 需求小于 work,可以尝试分配 FINISH[i] = 1; //说明该行(进程)状态为已分配 //回收资源 for (int k = 0; k < N; k++) { WORK[k] += ALLOCATION[i][k]; } P[l++] = i; //加入安全队列 i = -1; }else continue; } if(l == M){ //此时代表安全队列已满,说明当前分配安全 System.out.println("经安全性检查,系统安全,本次分配成功。\n"); System.out.println("安全序列是:"); for (i = 0; i < l; i++) { System.out.println(P[i]); if( i != l - 1) System.out.print("---->"); } System.out.println(); return true; } } System.out.println("系统不安全!!!! 本次资源申请不成功!!!!!!\n"); return false; }
-
银行家算法:
public void bank(){ System.out.println("-------- 银行家算法开始申请资源 ----------"); Scanner sc = new Scanner(System.in); int i,j; char flag = 'Y'; while (flag == 'Y' || flag == 'y'){ i = -1; //输入需要申请资源的进程号 while (i < 0 || i > M){ System.out.println("请输入需申请资源的进程号:"); i = sc.nextInt(); if(i < 0 || i >= M) System.out.println("输入的进程号不存在,请重新输入!"); } System.out.println("请输入进程 " + i + " 申请各类资源的数量:"); for (j = 0;j < N;j++){ System.out.print("资源" + j + ":"); Request[j] = sc.nextInt(); //输入请求大于需求,即不安全 if(Request[j] > NEED[i][j]){ System.out.println("\n进程 " + i+ "申请的资源大于进程" + i + "还需要" + j + "类资源的数量!! 若继续执行系统将处于不安全状态" ); flag = 'N'; break; }else { //输入需求大于可用,依旧不安全 if(Request[j] > AVAILABLE[j]){ System.out.println("\n进程 " + i+ "申请的资源大于进程" + i + "还需要" + j + "类资源的数量!! 若继续执行系统将处于不安全状态" ); flag = 'N'; break; } } } if(flag == 'Y' || flag == 'y'){ distribute(i); //调用 distribute(i),改变资源数 if(!check()){ //若系统不安全 restore(i); //调用 restore(i) 函数恢复资源数 output(); //输出资源分配情况 } }else { System.out.println(); } System.out.println("是否继续申请资源?(Y/N)"); flag = sc.next().charAt(0); } }
- 调用:
public static void main(String[] args) throws FileNotFoundException { //执行银行家算法 BankerAlgorithm bankerAlgorithm = new BankerAlgorithm(); }
-
解密银行家算法:操作系统资源管理的秘密武器
于 2025-02-11 19:18:35 首次发布