银行家算法是最著名的避免死锁的算法。下面用Java来实现它。
主要使用到的类是BankerAlgorithm
。
并且进程的信息是从文件中读入的。
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]; // M个进程还需要N类资源的资源量 int[] Request = new int[R]; // 请求资源个数 int[] P = new int[W]; //进程安全序列 String fileName = "D:\\data.txt";
public BankerAlgorithm() throws FileNotFoundException { System.out.println("\t\t 银 行 家 算 法"); System.out.println("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"); Scanner sc = new Scanner(new FileReader(fileName)); System.out.print("请输入总进程数:"); M = sc.nextInt(); System.out.println(M); System.out.println("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"); System.out.print("请输入总资源种类:"); 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.print(ALL_RESOURCE[i] + " "); } System.out.println("\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"); 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("\n占有资源超过了声明的该资源总数,请重新输入"); } while (MAX[i][j] > ALL_RESOURCE[j]); System.out.print(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("\n占有资源超过了声明的最大资源,请重新输入"); } while (ALLOCATION[i][j] > MAX[i][j]); System.out.print(ALLOCATION[i][j] + " "); } System.out.println(); } //初始化资源数量 int p; for (int j = 0; j < N; j++) { p = ALL_RESOURCE[j]; for (int i = 0; i < M; i++) { p = p - ALLOCATION[i][j];// 减去已经被占据的资源 AVAILABLE[j] = p; if (AVAILABLE[j] < 0) AVAILABLE[j] = 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("各进程还需要的资源数量:"); System.out.print(" "); 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("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"); System.out.println("各进程已经得到的资源量: "); System.out.print(" "); 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 j = 0; j < N; j++) { AVAILABLE[j] += Request[j]; ALLOCATION[k][j] -= Request[j]; NEED[k][j] += Request[j]; } }
//安全性检查 public boolean check() { int[] WORK = new int[R], FINISH = new int[W]; for (int j = 0; j < N; j++) WORK[j] = AVAILABLE[j]; for (int i = 0; i < M; i++) FINISH[i] = 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 经安全性检查,系统安全,本次分配成功。\n"); System.out.println("安全序列是:"); for (i = 0; i < l; i++) { System.out.print(P[i]); if (i != l - 1) System.out.print("-->"); } System.out.println(); return true; } } System.out.println("\n 系统不安全!!! 本次资源申请不成功!!!\n"); return false; }
public void bank() { 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.print("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + "\n" + " 请输入需申请资源的进程号:"); 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 // 若系统安全 output(); // 输出资源分配情况 } else System.out.println(); System.out.print(" 是否继续银行家算法演示,按'Y'或'y'键继续,按'N'或'n'键退出演示: "); flag = sc.next().charAt(0); } }
由于把主要算法最终都放在了构造器之中,因而使用时直接new BankerAlgorithm()
即可。