银行家算法

银行家算法

一种避免死锁的算法,由Dijkstra发明。
假定系统中有n个进程,m类资源,银行家算法使用的数据结构如下
1. 可利用资源向量Available[m]
Available[i]表示第i类资源的现有空闲数量。
2. 最大需求矩阵Max[n][m]
Max[i][j]表示第i个进程对第j类资源的最大需求。
3. 分配矩阵Allocation[n][m]
Allocation[i][j]表示第i个进程当前拥有第j类资源的数量。
4. 需求矩阵Need[n][m]
Need[i][j]表示第i个进程还需要第j类资源的数量。

Allocation + Need = Max

算法Java实现

下面这段代码是银行家算法的实现

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class Banker {
    private int resN;
    private int processN;

    private int[] available;
    private final int[][] MAX;
    private int[][] need;
    private int[][] allocation;

    private int[] work;
    private boolean[] finish;

    public Banker(int[] availableRes, int[][] max) {
        available = availableRes;
        resN = available.length;
        processN = max.length;
        MAX = max;
        need = new int[processN][resN];
        for (int i = 0; i < processN; i++) {
            for (int j = 0; j < resN; j++) {
                need[i][j] = MAX[i][j];
            }
        }
        allocation = new int[processN][resN]; // allocation + need = MAX;
        work = new int[resN];
        finish = new boolean[processN];
    }

    public boolean request(int process, int[] requestRes) {
        if (!validate(process, requestRes))
            return false;
        boolean result = bank(process, requestRes);
        printRequest(process, requestRes);
        printState();
        return result;
    }

    private boolean bank(int process, int[] requestRes) {
        // 1. 预分配
        for (int i = 0; i < resN; i++) {
            available[i] -= requestRes[i];
            allocation[process][i] += requestRes[i];
            need[process][i] -= requestRes[i];
        }
        // 2. 检查是否进入安全状态
        if (isSecureState())
            return true;
        // 3. 分配后进入非安全状态,取消分配
        for (int i = 0; i < resN; i++) {
            available[i] += requestRes[i];
            allocation[process][i] -= requestRes[i];
            need[process][i] += requestRes[i];
        }
        return false;
    }

    private boolean isSecureState() {
        int[] secure = new int[processN];
        for (int i = 0; i < resN; i++) {
            work[i] = available[i];
        }
        for (int i = 0; i < processN; i++) {
            finish[i] = false;
        }
        for (int i = 0; i < processN; i++) {
            // Find a process which need < work.
            for (int j = 0; j < processN; j++) {
                if ((!finish[j]) && isAvailableEnough(j)) {
                    for (int k = 0; k < resN; k++) {
                        work[k] += allocation[j][k];
                    }
                    secure[i] = j;
                    finish[j] = true;
                    break;
                }
                // The available is not enough for all processes.
                if (j == processN - 1) {
                    System.out
                            .println("Request fail. It will go to the unsecure state.");
                    return false;
                }
            }
        }
        System.out.print("The secure array : ");
        for (int i = 0; i < processN; i++) {
            System.out.print(secure[i] + " ");
        }
        System.out.println();
        return true;
    }

    private boolean isAvailableEnough(int process) {
        for (int i = 0; i < resN; i++) {
            if (work[i] < need[process][i])
                return false;
        }
        return true;
    }

    private boolean validate(int process, int[] requestRes) {
        for (int i = 0; i < resN; i++) {
            if (requestRes[i] > available[i]) {
                printRequest(process, requestRes);
                System.out.println("Request fail. Request for resource " + i
                        + " is larger than available.");
                printState();
                return false;
            } else if (requestRes[i] > need[process][i]) {
                printRequest(process, requestRes);
                System.out.println("Request fail. Request for resource " + i
                        + " is larger than process " + process + " needs.");
                System.out.println();
                printState();
                return false;
            }
        }
        return true;
    }

    public void printState() {
        System.out.print("Available = ");
        for (int i = 0; i < resN; i++) {
            System.out.print(available[i] + " ");
        }
        System.out.println();
        System.out.println("MAX    Allocation    Need");
        for (int i = 0; i < processN; i++) {
            for (int j = 0; j < resN; j++) {
                System.out.print(MAX[i][j] + " ");
            }
            System.out.print("  ");
            for (int j = 0; j < resN; j++) {
                System.out.print(allocation[i][j] + " ");
            }
            System.out.print("  ");
            for (int j = 0; j < resN; j++) {
                System.out.print(need[i][j] + " ");
            }
            System.out.println();
        }
        System.out.println();
    }

    private void printRequest(int process, int[] requestRes) {
        System.out.print("Request " + process + " = ");
        for (int i = 0; i < resN; i++) {
            System.out.print(requestRes[i] + " ");
        }
        System.out.println();
    }

    public static void main(String[] args) throws IOException {
        int[] available = { 10, 8, 7 };
        final int[][] MAX = { { 7, 5, 3 }, { 3, 2, 2 }, { 9, 0, 2 }, { 2, 2, 2 }, { 4, 3, 3 } };
        Banker banker = new Banker(available, MAX);

        BufferedReader is = new BufferedReader(new InputStreamReader(System.in));
        banker.printState();
        while (true) {
            try {
                System.out.print("Please input the request: ");
                String input = is.readLine();
                if ("q".equals(input))
                    break;
                String[] data = input.split(" ");
                int process = Integer.valueOf(data[0]);
                int[] requestRes = new int[available.length];
                for (int i = 0; i < available.length; i++) {
                    requestRes[i] = Integer.valueOf(data[i + 1]);
                }
                banker.request(process, requestRes);
            } catch (Exception e) {
                System.out.print("Error");
            }
        }
        is.close();
    }
}

现在来解释银行家算法的过程。
1. 进程i向系统提出资源请求。

    public boolean request(int process, int[] requestRes) {
        if (!validate(process, requestRes))
            return false;
        boolean result = bank(process, requestRes);
        printRequest(process, requestRes);
        printState();
        return result;
    }

requestRes表示对各类资源的申请数量。
2. request方法首先调用validate方法对资源请求进行审核。

    private boolean validate(int process, int[] requestRes) {
        for (int i = 0; i < resN; i++) {
            if (requestRes[i] > available[i]) { // 审核标准1
                printRequest(process, requestRes);
                System.out.println("Request fail. Request for resource " + i
                        + " is larger than available.");
                printState();
                return false;
            } else if (requestRes[i] > need[process][i]) { // 审核标准2
                printRequest(process, requestRes);
                System.out.println("Request fail. Request for resource " + i
                        + " is larger than process " + process + " needs.");
                printState();
                return false;
            }
        }
        return true;
    }

审核标准1,Request <= Available,若不满足,则表示可用资源不够。
审核标准2,Request <= Need,若不满足,则表示请求的资源数超出了需要的资源数。
3. 满足上述审核标准后,对进程i请求的资源进行预分配。

    private boolean bank(int process, int[] requestRes) {
        // 1. 预分配
        for (int i = 0; i < resN; i++) {
            available[i] -= requestRes[i];
            allocation[process][i] += requestRes[i];
            need[process][i] -= requestRes[i];
        }
        // 2. 检查是否进入安全状态
        if (isSecureState())
            return true;
        // 3. 分配后进入非安全状态,取消分配
        for (int i = 0; i < resN; i++) {
            available[i] += requestRes[i];
            allocation[process][i] -= requestRes[i];
            need[process][i] += requestRes[i];
        }
        return false;
    }

4. 对修改后的状态向量进行安全性算法检测,若分配后进入非安全状态,则取消分配,如上述代码第3步。
5. 安全性检测算法
查找是否存在安全序列。若在某一时刻,系统能按某种顺序为每个进程分配其所需的资源,直到最大需求,使每个进程都可顺利完成,则称此时的系统状态为安全状态,该序列为安全序列。

    private boolean isSecureState() {
        int[] secure = new int[processN];
        for (int i = 0; i < resN; i++) {
            work[i] = available[i];
        }
        for (int i = 0; i < processN; i++) {
            finish[i] = false;
        }
        for (int i = 0; i < processN; i++) {
            // 查找满足2个条件的进程:1.Finish[i]=false; 2.Need<=Work
            for (int j = 0; j < processN; j++) {
                if ((!finish[j]) && isAvailableEnough(j)) {
                    for (int k = 0; k < resN; k++) {
                        work[k] += allocation[j][k];
                    }
                    secure[i] = j;
                    finish[j] = true;
                    break;
                }
                // The available is not enough for all processes.
                if (j == processN - 1) {
                    System.out
                            .println("Request fail. It will go to the unsecure state.");
                    return false;
                }
            }
        }
        ...
        return true;
    }

    private boolean isAvailableEnough(int process) {
        for (int i = 0; i < resN; i++) {
            if (work[i] < need[process][i])
                return false;
        }
        return true;
    }

1.首先创建了长度为m的向量Work[m],长度为n的向量Finish[n],初始化Work=Available,Finish[n]=false;
2.查找满足如下2个条件的进程:1. Finish[i]=false; 2. Need<=Work。若没有这样的进程存在,则表示进程进入非安全状态。
3.如果找到满足条件进程i,则将Finish[i]设为true,表示当前可使用的资源数量可以让进程i正常结束,同时Work=Work+Allocation[i],表示进程i结束后,可使用的资源数。然后返回2继续查找。
4.如果所有进程,Finish都为true,那么表示有一个进程运行序列可以保证不会发生死锁,此时系统处于安全状态。反之,则系统处于不安全状态,并取消分配。

代码运行结果

读者可以自己运行测试。

Available = 10 8 7 
MAX    Allocation    Need
7 5 3   0 0 0   7 5 3 
3 2 2   0 0 0   3 2 2 
9 0 2   0 0 0   9 0 2 
2 2 2   0 0 0   2 2 2 
4 3 3   0 0 0   4 3 3 

Please input the request: 0 0 1 0
The secure array : 0 1 2 3 4 
Request 0 = 0 1 0 
Available = 10 7 7 
MAX    Allocation    Need
7 5 3   0 1 0   7 4 3 
3 2 2   0 0 0   3 2 2 
9 0 2   0 0 0   9 0 2 
2 2 2   0 0 0   2 2 2 
4 3 3   0 0 0   4 3 3 

Please input the request: 1 2 0 0
The secure array : 0 1 2 3 4 
Request 1 = 2 0 0 
Available = 8 7 7 
MAX    Allocation    Need
7 5 3   0 1 0   7 4 3 
3 2 2   2 0 0   1 2 2 
9 0 2   0 0 0   9 0 2 
2 2 2   0 0 0   2 2 2 
4 3 3   0 0 0   4 3 3 

Please input the request: 2 3 0 2
The secure array : 1 0 2 3 4 
Request 2 = 3 0 2 
Available = 5 7 5 
MAX    Allocation    Need
7 5 3   0 1 0   7 4 3 
3 2 2   2 0 0   1 2 2 
9 0 2   3 0 2   6 0 0 
2 2 2   0 0 0   2 2 2 
4 3 3   0 0 0   4 3 3 

Please input the request: 3 2 1 1
The secure array : 1 3 0 2 4 
Request 3 = 2 1 1 
Available = 3 6 4 
MAX    Allocation    Need
7 5 3   0 1 0   7 4 3 
3 2 2   2 0 0   1 2 2 
9 0 2   3 0 2   6 0 0 
2 2 2   2 1 1   0 1 1 
4 3 3   0 0 0   4 3 3 

Please input the request: 4 0 0 2
The secure array : 1 3 0 2 4 
Request 4 = 0 0 2 
Available = 3 6 2 
MAX    Allocation    Need
7 5 3   0 1 0   7 4 3 
3 2 2   2 0 0   1 2 2 
9 0 2   3 0 2   6 0 0 
2 2 2   2 1 1   0 1 1 
4 3 3   0 0 2   4 3 1 

Please input the request: 1 1 0 2
The secure array : 1 3 0 2 4 
Request 1 = 1 0 2 
Available = 2 6 0 
MAX    Allocation    Need
7 5 3   0 1 0   7 4 3 
3 2 2   3 0 2   0 2 0 
9 0 2   3 0 2   6 0 0 
2 2 2   2 1 1   0 1 1 
4 3 3   0 0 2   4 3 1 

Please input the request: 0 2 4 0
The secure array : 1 3 0 2 4 
Request 0 = 2 4 0 
Available = 0 2 0 
MAX    Allocation    Need
7 5 3   2 5 0   5 0 3 
3 2 2   3 0 2   0 2 0 
9 0 2   3 0 2   6 0 0 
2 2 2   2 1 1   0 1 1 
4 3 3   0 0 2   4 3 1 

Please input the request: 3 0 1 0
Request fail. It will go to the unsecure state.
Request 3 = 0 1 0 
Available = 0 2 0 
MAX    Allocation    Need
7 5 3   2 5 0   5 0 3 
3 2 2   3 0 2   0 2 0 
9 0 2   3 0 2   6 0 0 
2 2 2   2 1 1   0 1 1 
4 3 3   0 0 2   4 3 1 

Please input the request: 

算法意义

银行家算法虽然很有意义,但是缺乏实用价值。原因如下:
1. 因为很少有进程在运行前就知道它所需资源的最大值
2. 进程数在不断变化(新用户的登录或退出)
3. 原本可用的资源也可能突然间变得不可用(如磁带机可能会坏掉)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值