JAVA-银行家算法

银行家算法是一个避免死锁的著名算法,是由艾兹格.迪杰斯特拉设计的一种避免死锁产生的算法。它以银行借贷系统的分配策略为基础,判断并保证系统的安全运行。

一、背景介绍

在银行中,客户申请贷款的数量是有限的,每个客户在第一次申请贷款时要声明完成该项目所需的最大资金量,在满足所有贷款要求时,客户应及时归还。银行家在客户申请的贷款数量不超过自己拥有的最大值时,都应尽量满足客户的需要。在这样的描述中,银行家就好比操作系统,资金就是资源,客户就相当于要申请资源的进程。

安全序列:指一个进程序列{p1,......,pn}是安全的,即对于每一个进程pi(1<= i<=n),它以后尚需要的资源量不超过系统当前剩余资源量与所有进程pj(j<i)当前占有资源量之和。

 安全状态一定是没有死锁发生的。

不安全状态:不存在一个安全序列,不安全状态一定导致死锁。

二、相关数据结构

银行家算法中的数据结构
  • 设系统中有m种不同资源, n个进程
  • Available向量: 系统中尚未分配的每种资源的总量
  • Available[j]: 尚未分配的资源j的数量
  • Max矩阵: 各个进程对每种资源的最大需求量(进程事先声明)
  • Max[i, j](Claim[i,j]): 进程i 对资源j 的最大需求量
  • Allocation矩阵: 当前资源分配状况
  • Allocation[i, j]: 进程i获得的资源j的数量
  • Need矩阵: 每个进程还需要的资源的数量
  • Need[i, j]: 进程i尚需的资源j的数量
各数据结构之间的关系
  • Resource[j] = Available[j] + (Allocation[1, j] + Allocation[2, j] + … + Allocation[n, j])
  • Max[i, j] <= Resource[j]
  • Allocation[i, j] <= Max[i, j]
  • Allocation[i, j] + Need[i, j] =Max[i, j]
安全性算法

1. 设Work和Finish 分别是长度为m 和n 的向量,按如下方式进行初始化:
            Work = Available
            Finish [i] = false ( i =1,2, …, n)
2. 查找这样的i使其满足:(a) Finish [i] = false  (b) Need i <=Work
3. 如果没有这样的 i 存在,那么就转到第4步.
4. Work = Work + Allocation i Finish[i] = True 返回到第2步.
5. 如果对所有的i,Finish [i] == True ,那么系统处于安全状态

例题讲解1

R1,R2,R3的数量分别为(9,3,6); Available(1,1,2)

问:1.该时刻是否为安全状态

       2.进程A请求资源Request(1,0,1),能够分配吗?为什么?

解题步骤如下:(注:!!!圆圈序号表示做题方法,答案中不必出现。)

1.画出如下表格

①首先将available中的数字填在首行work中

②available(1,1,2)分别和A、B、C、D中的need相比较,倘若小于,则从上往下依次选择。例如B(1,0,2)小于则将B填入第一行,其后need、Allocation依次填入

③接着计算work+allocation的值与R1R2R3(9,3,6)相比较,小于则为true

④将上一行中的work+allocation的值填入下一行work中,接着重复②之后的操作。

⑤直到填完最后一个进程,finish都为true则此时产生了一个安全序列。

2.①将requestA和needA和Available相比较,若小于二者则可继续判断,否则不够分配。

RequestA(1,0,1)<=Need(2,2,2)
RequestA(1,0,1)<=Available(1,1,2)

②修改A的allocation和need,allocation+requestA , need-requestA 并将值填入其中。
假定满足进程A的要求,为它分配所申请的资源,并且修改AllocaitonA 和 NeedA,得到:

此时:Available=(0,1,1):不能分配给任何进程;因此不能分配此次请求。

③此时available-requsetA得到(0,1,1)此时,更新A的状态,重复第一问判断是否存在安全状态。通过比较我们发现available(0,1,1)小于任何一个进程的Need故无法进行分配

例题讲解2

设系统在T0时刻系统状态如下:剩余资源向量为: A=(2, 3, 3)

问:① T0时刻是否为安全状态?若是,请给出安全序列。
       ② 在T0时刻若进程P2请求资源(0,3,4),是否能实施资源分配?为什么?
       ③ 在②的基础上,若进程P4请求资源(2,0,1),是否能实施资源分配?为什么?

解析:与题1不同的是,题2并未给出一个系统的表,因此需要在草稿本上列出表格的大概状态。最大资源需求(Max)已分配资源数量(allocation)剩余资源向量(available)

need = max - allocation,其余步骤参考题1 即可

答案:1. 是,安全序列:p4, p5, p1, p2, p3

            2.因为 R(0,3,4)> A (2,3,3,)所以不能分配。

            3.因为R(2,0,1)<=N4(2, 0,1)且 < A(2,3,3)假设可以满足,则N4=(0, 0, 0), A= (0,3,2),在此基础上,是安全的,因此可以实施分配。安全序列为:p4,p5,p1,p2,p3

三、参考示例代码

import java.util.Arrays;

class BankersAlgorithm {
    private int[][] max;   // 最大需求矩阵
    private int[][] allocation;   // 已分配资源矩阵
    private int[][] need;   // 剩余需求矩阵
    private int[] available;   // 可用资源向量
    private int[][] request;   // 请求资源矩阵

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

        int numOfProcesses = max.length;
        int numOfResources = available.length;

        this.need = new int[numOfProcesses][numOfResources];
        this.request = new int[numOfProcesses][numOfResources];

        // 计算剩余需求矩阵
        for (int i = 0; i < numOfProcesses; i++) {
            for (int j = 0; j < numOfResources; j++) {
                need[i][j] = max[i][j] - allocation[i][j];
            }
        }
    }

    public void requestResources(int pid, int[] request) {
        System.out.println("进程 " + pid + " 请求资源: " + Arrays.toString(request));
        boolean safe = checkSafety(pid, request);

        if (safe) {
            System.out.println("请求通过,为进程 " + pid + " 分配资源 " + Arrays.toString(request));
            allocateResources(pid, request);
        } else {
            System.out.println("请求被拒绝,进程 " + pid + " 等待...");
        }
    }

    private boolean checkSafety(int pid, int[] request) {
        int numOfProcesses = max.length;
        int numOfResources = available.length;

        int[] work = Arrays.copyOf(available, numOfResources);
        boolean[] finish = new boolean[numOfProcesses];

        // 设置该进程的请求资源情况
        for (int i = 0; i < numOfResources; i++) {
            allocation[pid][i] += request[i];
            need[pid][i] -= request[i];
            work[i] -= request[i];
        }

        int count = 0;   // 用于统计已分配资源的进程数
        boolean hasFinished = true;   // 标识是否存在符合条件的进程

        while (count < numOfProcesses && hasFinished) {
            hasFinished = false;

            for (int i = 0; i < numOfProcesses; i++) {
                if (!finish[i] && checkNeedLessOrEqual(work, need[i])) {
                    // 分配资源给进程
                    for (int j = 0; j < numOfResources; j++) {
                        work[j] += allocation[i][j];
                    }
                    finish[i] = true;
                    count++;
                    hasFinished = true;
                }
            }
        }

        // 恢复该进程的请求资源情况
        for (int i = 0; i < numOfResources; i++) {
            allocation[pid][i] -= request[i];
            need[pid][i] += request[i];
            work[i] += request[i];
        }

        return count == numOfProcesses;
    }

    private boolean checkNeedLessOrEqual(int[] work, int[] need) {
        for (int i = 0; i < work.length; i++) {
            if (work[i] < need[i]) {
                return false;
            }
        }
        return true;
    }

    private void allocateResources(int pid, int[] request) {
        int numOfResources = available.length;

        for (int i = 0; i < numOfResources; i++) {
            available[i] -= request[i];
            allocation[pid][i] += request[i];
            need[pid][i] -= request[i];
        }
    }
}

public class TestBanker {
    public static void main(String[] args) {
        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}
        };

        int[] available = {3, 3, 2};

        // 继续编写您想要的代码逻辑
    }
}
  • 0
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值