解密银行家算法:操作系统资源管理的秘密武器

  1.  概述:
    1. 银行家算法是操作系统领域中用于避免死锁的经典算法
    2. 其核心思想是通过模拟资源分配的过程,系统在进行资源分配之前,应先计算此次分分配资源的安全性,若分配不会导致系统进入不安全状态,则分配,否则等待
    3. 实现银行家算法,系统必须设置若干数据结构
  2. 死锁(Deadlock):
    1. 是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去
    2. 称此时系统处于死锁状态或系统产生了死锁
    3. 称这些永远在互相等待的进程成为死进程
  3. 资源与进程:
    1. 在操作系统中,资源是有限的,而多个进程会竞争这些资源
    2. 银行家算法通过以下关键数据结构来描述资源分配的状态:
      1. 资源向量(Available):表示系统中当前可用的每种资源的数量
      2. 最大需求矩阵(Max):记录每个进程对每种资源的最大需求量
      3. 分配矩阵(Allocation):表示当前已分配给每个进程的资源数量
      4. 需求矩阵(Need):表示每个进程还需要的资源数量,计算公式为:Need = Max - Allocation
  4. 安全状态:
    1. 银行家算法的核心目标是确保系统始终处于 "安全状态"
    2. 所谓安全状态,是指在一种资源分配顺序,使得所有进程都能顺利完成,而不会导致死锁
    3. 系统需要满足以下条件:
      1. 每个进程的资源请求不超过其最大需求
      2. 系统能够找到一个安全序列,使得每个进程都能获得所需资源并完成执行
  5. 不安全状态:
    1. 不存在一个安全序列。不安全状态不一定导致死锁
  6. 工作流程:
    1. 初始化:
      1. 在算法开始前,需要初始化以下数据结构:
        1. Need:每个进程还需要的资源数量
        2. Allocation:当前已分配给每个进程的资源数量
        3. Max:每个进程的最大资源需求
        4. Available:系统当前可用的资源数量
    2. 资源请求处理:
      1. 当一个进程请求资源时,系统会执行以下步骤:

        1. 检查请求合法性:如果请求的资源数量超过进程的最大进程需求,请求将被拒绝
        2. 检查资源可用性:如果请求的资源数量超过系统当前可用资源,进程需要等待
        3. 试探性分配:假设分配资源,并跟新 Available、Allocation 和 Need 矩阵
        4. 安全性检查:检查系统是否仍处于安全状态
          1. 如果是,则正式分配资源
          2. 否则,撤销试探性分配
    3. 安全性检查:
      1. 安全性检查是银行家算法的核心步骤,其目的是找到一个安全序列,步骤如下:
        1. 初始化工作项量 Work 和完成标志 Finish
        2. 查找一个未完成的进程,其资源需求小于等于 Work
        3. 如果找到这样的进程,假设其可以完成,并释放其占用的资源
        4. 重复上述步骤,直到所有进程都完成或无法找到满足条件的进程
  7. 实现银行家算法:
    1. 定义全局变量:
      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";
    2. txt 文件需要的数据():
      3
      2
      10 5
      7 5
      3 2
      6 3
      2 1
      1 1
      2 1
      
    3. 构造器:
      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();
              }
          }
    4. 输出:
      //输出资源信息
          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];
              }
          }
    5. 安全性检查:
      //安全性检查
          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;
          }
    6. 银行家算法:
       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);
              }
          }
    7. 调用:
      public static void main(String[] args) throws FileNotFoundException {
              //执行银行家算法
              BankerAlgorithm bankerAlgorithm = new BankerAlgorithm();
          }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值