银行家算法(Banker‘s Algorithm)详解(含 Java 实现)

银行家算法是一种 死锁避免(Deadlock Avoidance) 算法,它用于 动态分配系统资源,确保系统始终处于 安全状态(Safe State),避免进入死锁。

本篇博客将深入讲解:

  1. 银行家算法的核心概念
  2. 算法的执行步骤(含示例)
  3. Java 实现银行家算法
  4. 银行家算法的优势与局限性

1. 银行家算法的核心概念

1.1 什么是银行家算法?

银行家算法由 Edsger Dijkstra 提出,它的名字来源于 银行借贷系统

银行不会一次性把所有资金借给客户,而是保证即使有客户申请贷款,银行仍能满足所有客户的最低需求,以防止资金枯竭。

同理,在计算机资源分配中:

  • 进程向系统申请资源时,银行家算法会先检查资源是否足够。
  • 如果满足条件,系统会假设分配资源后仍处于安全状态,才会真正分配。
  • 如果分配资源会导致系统进入不安全状态,则拒绝该申请

1.2 关键术语

银行家算法中,主要涉及以下数据结构:

名称作用
Max进程需要的最大资源数
Allocation进程当前已分配的资源
Need进程仍需要的资源 = Max - Allocation
Available系统当前可用的资源

假设系统有 3 类资源 A、B、C,现有 5 个进程(P0 ~ P4),初始资源情况如下:

资源状态

资源类型ABC
Available(当前可用)332

进程的最大需求(Max)

进程ABC
P0753
P1322
P2902
P3222
P4433

进程当前已分配的资源(Allocation)

进程ABC
P0010
P1200
P2302
P3211
P4002

进程仍需要的资源(Need = Max - Allocation)

进程ABC
P0743
P1122
P2600
P3011
P4431

2. 银行家算法的执行步骤

2.1 资源分配步骤

  1. 检查请求是否超过 Need
    • Request ≤ Need,继续,否则出错(进程请求超过最大需求)。
  2. 检查请求是否超过 Available
    • Request ≤ Available,则继续,否则进程需等待资源释放。
  3. 尝试分配资源
    • 临时分配 Available -= RequestAllocation += RequestNeed -= Request
  4. 安全性检测
    • 检查分配后是否能找到一个安全序列。
    • 若有安全序列,则分配成功,否则回滚。

2.2 安全性检测步骤

  1. 标记所有进程为未完成(Finish = false)。
  2. 找到一个进程 Pi,使得 Need[i] ≤ Available
  3. 假设分配资源给 Pi,执行完后释放 Pi 的资源(Available += Allocation[i])。
  4. 重复 2-3,直到所有进程都能执行完毕,即 Finish[i] = true
  5. 若所有进程都完成,则系统安全,否则回滚请求。

3. Java 实现银行家算法

import java.util.Arrays;

public class BankersAlgorithm {
    private final int P;  // 进程数量
    private final int R;  // 资源种类数量
    private int[] available;  // 可用资源
    private int[][] max;  // 最大需求矩阵
    private int[][] allocation;  // 已分配矩阵
    private int[][] need;  // 仍需资源矩阵

    public BankersAlgorithm(int P, int R, int[] available, int[][] max, int[][] allocation) {
        this.P = P;
        this.R = R;
        this.available = available;
        this.max = max;
        this.allocation = allocation;
        this.need = new int[P][R];

        // 计算 Need = Max - Allocation
        for (int i = 0; i < P; i++) {
            for (int j = 0; j < R; j++) {
                need[i][j] = max[i][j] - allocation[i][j];
            }
        }
    }

    // 安全性检查
    private boolean isSafe() {
        int[] work = Arrays.copyOf(available, R);
        boolean[] finish = new boolean[P];

        int count = 0;
        while (count < P) {
            boolean found = false;
            for (int i = 0; i < P; i++) {
                if (!finish[i]) {
                    boolean canExecute = true;
                    for (int j = 0; j < R; j++) {
                        if (need[i][j] > work[j]) {
                            canExecute = false;
                            break;
                        }
                    }
                    if (canExecute) {
                        for (int j = 0; j < R; j++) {
                            work[j] += allocation[i][j];
                        }
                        finish[i] = true;
                        found = true;
                        count++;
                    }
                }
            }
            if (!found) return false;
        }
        return true;
    }

    // 资源请求
    public boolean requestResources(int processId, int[] request) {
        for (int i = 0; i < R; i++) {
            if (request[i] > need[processId][i] || request[i] > available[i]) {
                return false;
            }
        }
        for (int i = 0; i < R; i++) {
            available[i] -= request[i];
            allocation[processId][i] += request[i];
            need[processId][i] -= request[i];
        }
        if (isSafe()) {
            return true;
        } else {
            for (int i = 0; i < R; i++) {
                available[i] += request[i];
                allocation[processId][i] -= request[i];
                need[processId][i] += request[i];
            }
            return false;
        }
    }

    public static void main(String[] args) {
        int P = 5, R = 3;
        int[] available = {3, 3, 2};
        int[][] max = {{7, 5, 3}, {3, 2, 2}, {9, 0, 2}, {2, 2, 2}, {4, 3, 3}};
        int[][] allocation = {{0, 1, 0}, {2, 0, 0}, {3, 0, 2}, {2, 1, 1}, {0, 0, 2}};

        BankersAlgorithm ba = new BankersAlgorithm(P, R, available, max, allocation);
        System.out.println("系统是否安全: " + ba.isSafe());
    }
}

总结

银行家算法可以 有效避免死锁,但计算复杂度较高,适用于静态资源分配场景。在实际应用中,现代操作系统更倾向于 死锁检测与资源抢占机制。🚀

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值