你知道银行家算法吗

459 阅读4分钟

1.什么是银行家算法

银行家算法(Banker's Algorithm)是一种资源分配算法,用于避免死锁(Deadlock)的发生。它最初是由艾克斯·汉克森(Edsger Dijkstra)于1965年提出的。

在多道程序环境下,进程可能会争夺有限的资源,资源包括内存、CPU时间、文件句柄等等,如果这些资源不正确地分配给进程,就可能导致死锁的发生,即进程无法向前推进,因为它需要的资源被其他进程占用,而其他进程也需要它占用的资源。

银行家算法的目的就是保证系统能够分配资源,避免死锁的发生。它基于以下假设:

1. 每个进程申请资源时,必须指定它需要的最大资源数量。

2. 每个进程在申请资源之前,必须先申请所有已分配给它的资源。

3. 系统在分配资源之前,必须检查分配资源后是否会导致死锁的发生。

银行家算法通过计算系统中所有进程当前需要的资源数量和可用的资源数量来决定是否能够分配资源。如果资源数量充足,系统会将资源分配给进程,并假定这些资源能够一直保持分配状态,直到进程释放它们。如果资源数量不足,系统会将进程的请求放入等待队列,直到有足够的资源可以分配给它。

银行家算法实现的关键是银行家数据结构,它存储了系统中所有进程需要的资源数量已经分配给它们的资源数量可用的资源数量。在每次分配或释放资源时,银行家算法会重新计算系统中所有进程的资源需求和可用资源数量,以判断是否能够分配资源,从而保证系统的安全性和避免死锁的发生。

2.初步理解一下

2.1.初始化
    1.1. available:一个长度为m的向量,表示每种资源可用的数量
    1.2. max:一个n x m的矩阵,表示每个进程最多需要的资源数量
    1.3. allocation:一个n x m的矩阵,表示每个进程当前已经分配的资源数量
    1.4. need:一个n x m的矩阵,表示每个进程还需要的资源数量
2.2.检查进程是否可以分配资源
     2.2.1. 找到一个满足以下条件的进程:

         a. 进程还需要的资源数量小于等于可用的资源数量

         b. 分配给这个进程所需的资源不会导致死锁

    2.2.2. 如果找到这样的进程,则分配资源给它,并更新银行家数据结构

    2.2.3. 如果找不到这样的进程,则认为系统进入死锁状态,退出算法
2.3 进程释放资源
     当一个进程释放资源时,更新银行家数据结构
2.4 重复步骤2和步骤3,直到所有进程都完成或者系统进入死锁状态     
   

3.看代码理解

import java.util.Arrays;

public class BankersAlgorithm {
    
    private int numOfProcesses;      // 进程的数量
    private int numOfResources;      // 资源的数量
    private int[] available;         // 每种资源可用的数量
    private int[][] max;             // 每个进程最多需要的资源数量
    private int[][] allocation;      // 每个进程当前已经分配的资源数量
    private int[][] need;            // 每个进程还需要的资源数量
    
    public BankersAlgorithm(int[] available, int[][] max, int[][] allocation) {
        this.numOfProcesses = max.length;
        this.numOfResources = available.length;
        this.available = Arrays.copyOf(available, available.length);
        this.max = new int[numOfProcesses][numOfResources];
        this.allocation = new int[numOfProcesses][numOfResources];
        this.need = new int[numOfProcesses][numOfResources];
        
        for (int i = 0; i < numOfProcesses; i++) {
            for (int j = 0; j < numOfResources; j++) {
                this.max[i][j] = max[i][j];
                this.allocation[i][j] = allocation[i][j];
                this.need[i][j] = max[i][j] - allocation[i][j];
            }
        }
    }
    
    public boolean isSafeState() {
        boolean[] finish = new boolean[numOfProcesses];
        int[] work = Arrays.copyOf(available, available.length);
        int count = 0;
        
        while (count < numOfProcesses) {
            boolean found = false;
            
            for (int i = 0; i < numOfProcesses; i++) {
                if (!finish[i] && hasEnoughResources(work, need[i])) {
                    found = true;
                    finish[i] = true;
                    for (int j = 0; j < numOfResources; j++) {
                        work[j] += allocation[i][j];
                    }
                    count++;
                }
            }
            
            if (!found) {
                return false;
            }
        }
        
        return true;
    }
    
    private boolean hasEnoughResources(int[] work, int[] need) {
        for (int i = 0; i < work.length; i++) {
            if (work[i] < need[i]) {
                return false;
            }
        }
        return true;
    }
    
    public static void main(String[] args) {
        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(available, max, allocation);
        if (ba.isSafeState()) {
            System.out.println("系统是安全的状态");
        } else {
            System.out.println("系统是不安全的状态");
        }
    }
}

解释如下:

假设有5个进程 P0、P1、P2、P3 和 P4,以及3种资源 A、B 和 C。每个进程最多需要的资源数量如下:

进程ABC
P0753
P1322
P2902
P3222
P4433

同时,已经有一些资源已经被分配给了这些进程,分配情况如下:

进程ABC
P0010
P1200
P2302
P3211
P4002

另外,现在可用资源数量为:

ABC
332

在执行上述代码后,程序会输出 "系统是安全的状态"。这意味着当前系统处于安全状态,所有进程都能够完成并释放它们所持有的资源,不会出现死锁。