避免死锁(银行家算法)

课程名称: 操作系统 实验名称: _避免死锁(银行家算法)

一 、实验目的

  1. 加深对死锁概念的理解。
  2. 能够利用银行家算法,有效避免死锁的发生,或检测死锁的存在。

二 实验内容

实验要求用高级语言编写和调试一个简单的银行家算法程序。加深了解有关资源申请、避免死锁等概念,并体会和了解死锁和避免死锁的具体实施方法。
1.设计进程对各类资源最大申请表示及初值确定。
2.设定系统提供资源初始状况。
3.设定每次某个进程对各类资源的申请表示。
4.编制程序,依据银行家算法,决定其申请是否得到满足。

三 实验分析

  1. 设计程序类Bank,在其中设计两个类:Sources资源类和Processo类用于管理资源和进程的调度,
    i. Bank拥有一个系统字段和可分配资源字段allSources
    ii. 拥有一个分配资源的方法:Assign(),将进程的资源请求进行处理
    iii. 拥有一个检查资源分配后,是否能安全运行的checkSafeQueue方法

  2. 在类Sources中主要设计的是三个字段,用于标志A,B,C类,这三类资源

  3. 在类Processor中 设计有三个字段
    i. 字段name属于String类,用与标记进程的名字
    ii . 字段maxSources属于Sources类,用于说明程序的最大资源占用
    III : 字段allSources属于Sources类,用于说明当前程序已经分配有的内容
    iv. 字段needSources属于Sources类,用于说明当前程序最多还能申请的最大资源
    4.程序最后设计了一个test()方法,用与测试程序的状态测试函数对参数进行了初始化,并设计了从键盘输入进行检测数据的正确性,数据请看实验结果

四 实验程序设计

package com.rainplus.banker;  
2.	import java.util.Scanner;  
3.	public class Bank {  
4.	// private Sources sysSources = new Sources(10, 5, 7);  
5.	private Sources allSources = new Sources(3, 3, 2);// TODO  
6.	// 资源类假设一共三类资源;  
7.	class Sources {  
8.	    private int A;  
9.	    private int B;  
10.	    private int C;  
11.	    public Sources(int B, int A, int C) {  
12.	        super();  
13.	        this.B = B;  
14.	        this.A = A;  
15.	        this.C = C;  
16.	    }  
17.	    public Sources(Sources sources) {  
18.	        super();  
19.	        this.B = sources.getB();  
20.	        this.A = sources.getA();  
21.	        this.C = sources.getC();  
22.	        }  
23.	    public int getB() {  
24.	            return B;  
25.	    }  
26.	    public void setB(int B) {  
27.	            this.B = B;  
28.	        }  
29.	    public int getA() {  
30.	            return A;  
31.	        }  
32.	    public void setA(int A) {  
33.	            this.A = A;  
34.	        }  
35.	    public int getC() {  
36.	            return C;  
37.	    }  
38.	    public void setC(int C) {  
39.	        this.C = C;  
40.	        }  
41.	    }  
42.	// 进程类,包进程使用最大内存,当前已分配内存,和需要分配内存  
43.	class Processor {  
44.	    private String name;  
45.	    private Sources maxSources;  
46.	    private Sources allSources;  
47.	    private Sources needSources;  
48.	    public String getName() {  
49.	            return name;  
50.	        }  
51.	    public void setName(String name) {  
52.	            this.name = name;  
53.	    }  
54.	    public Sources getMaxSources() {  
55.	        return maxSources;  
56.	}  
57.	    public void setMaxSources(Sources maxSources) {  
58.	        this.maxSources = maxSources;  
59.	    }   
60.	    public Sources getNeedSources() {  
61.	        return needSources;  
62.	    }  
63.	    public void setNeedSources(Sources needSources) {  
64.	        this.needSources = needSources;  
65.	    }  
66.	    public Sources getAllSources() {  
67.	        return allSources;  
68.	    }  
69.	    public void setAllSources(Sources allSources) {  
70.	        this.allSources = allSources;  
71.	    }  
72.	    }  
73.	// 显示当前系统和各个进程的资源使用情况  
74.	public void showdata(Processor[] processors) {  
75.	// 显示当前可用资源  
76.	    System.out.print("当前系统可分配资源为:");  
77.	    showSources(allSources);  
78.	    System.out.println("-----------------进程状态-------------");  
79.	    System.out.println("进程号      Max    Allocation      Need   ");  
80.	    System.out.println("     A B C     A B C       A B C");  
81.	    for (int i = 0; i < processors.length; i++) {  
82.	        System.out.print(processors[i].getName() + "   "  
83.	                + processors[i].getMaxSources().getA() + " "  
84.	                + processors[i].getMaxSources().getB() + " "  
85.	                + processors[i].getMaxSources().getC() + "     ");  
86.	        System.out.print(processors[i].getAllSources().getA() + " "  
87.	                + processors[i].getAllSources().getB() + " "  
88.	                + processors[i].getAllSources().getC() + "       ");  
89.	        System.out.println(processors[i].getNeedSources().getA() + " "  
90.	                + processors[i].getNeedSources().getB() + " "  
91.	                + processors[i].getNeedSources().getC() + " ");  
92.	        }  
93.	        System.out.println("-----------------------------------");  
94.	        }// 显示资源的数据  
95.	public void showSources(Sources sources) {  
96.	    System.out.println("A:" + sources.getA() + " B:" + sources.getB()  
97.	        + " C:" + sources.getC());  
98.	}  
99.	public boolean assign(Processor[] processors, int requestNum, Sources req) {  
100.	    Processor pro = processors[requestNum];  
101.	    if (!(req.getA() <= pro.getNeedSources().getA()&& req.getB() <= pro.getNeedSources().getB() && req.getC() <= pro.getNeedSources().getC())) {  
102.	        System.out.println("请求的资源数超过了所需要的最大值,分配错误");  
103.	        return false;  
104.	    }  
105.	    if (!(req.getA() <= allSources.getA()&& req.getB() <= allSources.getB() && req.getC() <= allSources.getC())) {  
106.	        System.out.println("尚无足够资源分配,必须等待");  
107.	        return false;  
108.	    }  
109.	// 分配资源  
110.	    allSources.setA(allSources.getA() - req.getA());  
111.	    allSources.setB(allSources.getB() - req.getB());  
112.	    allSources.setC(allSources.getC() - req.getC());  
113.	    pro.getAllSources().setA(pro.getAllSources().getA() + req.getA());  
114.	    pro.getAllSources().setB(pro.getAllSources().getB() + req.getB());  
115.	    pro.getAllSources().setC(pro.getAllSources().getC() + req.getC());  
116.	    pro.getNeedSources().setA(pro.getNeedSources().getA() - req.getA());  
117.	    pro.getNeedSources().setB(pro.getNeedSources().getB() - req.getB());  
118.	    pro.getNeedSources().setC(pro.getNeedSources().getC() - req.getC());  
119.	    boolean flag = checkSafeQueue(processors, allSources);// 进行安全性检查并返回是否安全  
120.	    if (flag == true) {System.out.println("能够安全分配");  
121.	        return true;  
122.	    } else {System.out.println("不能够安全分配");  
123.	            return false;  
124.	    }  
125.	    }  
126.	    public boolean checkSafeQueue(Processor[] pros, Sources all) {  
127.	    Sources temp = new Sources(all);  
128.	    boolean assigned[] = new boolean[5];  
129.	    int i = 0;  
130.	    //收回  
131.	    while (i < 5) {if (!assigned[i] && temp.getA() >= pros[i].getNeedSources().getA()  
132.	        && temp.getB() >= pros[i].getNeedSources().getB()&& temp.getC() >= pros[i].getNeedSources().getC()) {  
133.	            temp.setA(temp.getA() + pros[i].getAllSources().getA());  
134.	            temp.setB(temp.getB() + pros[i].getAllSources().getB());  
135.	            temp.setC(temp.getC() + pros[i].getAllSources().getC());  
136.	            System.out.println("分配成功的是:" + pros[i].getName());  
137.	            assigned[i] = true;  
138.	            i = 0;  
139.	    } else {  
140.	        i++;  
141.	    }  
142.	    }  
143.	    for (i = 0; i < 5; i++) {  
144.	        if (assigned[i] == false)  
145.	    return false;  
146.	    }  
147.	    return true;  
148.	    }  
149.	        public void test() {  
150.	        int processNum = 5;  
151.	// 初始化进程数据  
152.	    Sources[] all = new Sources[processNum];  
153.	    Sources[] max = new Sources[processNum];  
154.	    Sources[] need = new Sources[processNum];  
155.	    int[][] allData = { { 0, 1, 0 }, { 2, 0, 0 }, { 3, 0, 2 }, { 2, 1, 1 },{ 0, 0, 2 } };  
156.	    int[][] maxData = { { 7, 5, 3 }, { 3, 2, 2 }, { 9, 0, 2 }, { 2, 2, 2 },{ 4, 3, 3 } };  
157.	    int[][] needData = { { 7, 4, 3 }, { 1, 2, 2 }, { 6, 0, 0 },{ 0, 1, 1 }, { 4, 3, 1 } };  
158.	    for (int i = 0; i < processNum; i++) {  
159.	        all[i] = new Sources(allData[i][0], allData[i][1], allData[i][2]);  
160.	        max[i] = new Sources(maxData[i][0], maxData[i][1], maxData[i][2]);  
161.	        need[i] = new Sources(needData[i][0], needData[i][1],needData[i][2]);  
162.	    }  
163.	    Processor[] processors = new Processor[processNum];  
164.	for (int i = 0; i < processors.length; i++) {  
165.	    processors[i] = new Processor();  
166.	    processors[i].setName("P" + i);  
167.	    processors[i].setMaxSources(max[i]);  
168.	    processors[i].setAllSources(all[i]);  
169.	    processors[i].setNeedSources(need[i]);  
170.	}  
171.	    showdata(processors);  
172.	    Scanner s = new Scanner(System.in);  
173.	    int requestNum = 0;  
174.	    int[] input = { 0, 0, 0 };  
175.	    Sources requestSources = new Sources(0, 0, 0);  
176.	while (true)// 循环进行分配  
177.	{  
178.	    System.out.println("请输入要请求的进程号(0--4):");  
179.	    requestNum = s.nextInt();  
180.	    System.out.println("请输入请求的资源数目:");  
181.	    for (int i = 0; i < 3; i++) {//shuru 1 0 1  
182.	        input[i] = s.nextInt();  
183.	    }  
184.	        requestSources.setA(input[0]);  
185.	        requestSources.setB(input[1]);  
186.	        requestSources.setC(input[2]);  
187.	        assign(processors, requestNum, requestSources);  
188.	        showdata(processors);  
189.	}  
190.	}  
191.	public static void main(String[] args) {  
192.	    new Bank().test();  
193.	    }  
194.	}  

五 实验结果

/**/范例 1. 正确安全分配:
当前系统可分配资源为:A:3B:3 C:2
-----------------进程状态-------------
进程号 Max Allocation Need
A B C A B C A B C
P0 5 7 3 1 0 0 4 7 3
P1 2 3 2 0 2 0 2 1 2
P2 0 9 2 0 3 2 0 6 0
P3 2 2 2 1 2 1 1 0 1
P4 3 4 3 0 0 2 3 4 1

请输入要请求的进程号(0–4):1
请输入请求的资源数目:102
分配成功的是:P1
分配成功的是:P3
分配成功的是:P0
分配成功的是:P2
分配成功的是:P4
能够安全分配
前系统可分配资源为:A:2B:3 C:0
-----------------进程状态-------------
进程号 Max Allocation Need
A B C A B C A B C
P0 5 7 3 1 0 0 4 7 3
P1 2 3 2 1 2 2 1 1 0
P2 0 9 2 0 3 2 0 6 0
P3 2 2 2 1 2 1 1 0 1
P4 3 4 3 0 0 2 3 4 1

请输入要请求的进程号(0–4):
 2.不能安全运行:
当前系统可分配资源为:A:3B:3 C:2
-----------------进程状态-------------
进程号 Max Allocation Need
A B C A B C A B C
P0 5 7 3 1 0 0 4 7 3
P1 2 3 2 0 2 0 2 1 2
P2 0 9 2 0 3 2 0 6 0
P3 2 2 2 1 2 1 1 0 1
P4 3 4 3 0 0 2 3 4 1

请输入要请求的进程号(0–4):4
请输入请求的资源数目:3 3 1
不能够安全分配
当前系统可分配资源为:A:0B:0 C:1
-----------------进程状态-------------
进程号 Max Allocation Need
A B C A B C A B C
P0 5 7 3 1 0 0 4 7 3
P1 2 3 2 0 2 0 2 1 2
P2 0 9 2 0 3 2 0 6 0
P3 2 2 2 1 2 1 1 0 1
P4 3 4 3 3 3 3 0 1 0
-----------------------------------**
请输入要请求的进程号(0–4):
//
试验过程
情况1:输入进程号为3,请求资源为0 0 1
如下情况大概是想要为进程号分配的资源超过系统现存资源的情况,系统会出现拒绝分配的情况,所以系统的可以分配的资源依旧是3 3 2

接下来,为进程3分配资源为1 0 0

由于请求分配的资源在系统可以分配的范围之内,所以系统给进程3分配请求的资源数目,分配完成后,系统可分配的资源编程 2 3 2,下一步,系统会自动检测,剩余的可分配是否可以为其他进程合理分配;由于p1仅需要2 1 2资源,系统可分配的资源在这个范围之内,可以成功分配P1,剩余的可分配资源为 0 2 0 ,然后收回P1,系统可分配资源变成2 5 2,对于P3所需的0 0 1完全满足,于是可以成功完成进程P3,然后收回,变成 4 7 3,刚好可以完成P0进程所需的4 7 3 ,然后再次回收资源,变成 5 7 3,满足P4的进程,因此,初始请求分配0 0 1的情况下,系统可以进行安全分配。
情况2:遇见死锁

为进程P1请求分配资源为系统最大的分配资源3 3 2 时,由于进程P1完成的资源需求量超过系统最大可分配资源,于是,P1进程并不能完成,同时,由于请求资源是小于等于系统的最大可分配资源,所以系统将P1的请求分配给了P1,这导致现在系统内部的可分配资源数目变成0,即是系统没有可以分配的资源,但是分配出去的资源由于进程没有结束,所以不能被收回,于是,现在P1完不成,但是,其他的进程也不能进行下去,造成了目前死锁的局面。
情况3:为进程P0分配资源变成3 0 0

由于为进程P0分配的资源是3 0 0,小于进程P0的需求值,于是系统自动分配,但是,分配过后,P0并不能达到最大进程值,所以依旧在继续,但是不能被完成,同时,系统剩余的进程不能完成其他进程的需求,分配给P0的资源不能自动收回,所以,系统再次陷入死锁。但是当为P0分配值为2 0 0时,就可以避免死锁

1 0 0同样可以,要求是剩余的系统可分配资源可以满足其他任何进程的需求。
情况4:对于进程P1

为进程P1请求分配资源2 1 2,进程P1完成,所占有的资源全部还给系统,所以此刻的系统可分配资源为 3 5 2,可以完成P3 1 0 1 的进程需求,随后回收资源,可分配资源变成4 7 3 ,先完成进程P0,随后可分配资源变成5 7 3,完成P4进程,所以,可以有效避免死锁,系统可以安全分配。
情况5:为P4进程,分配资源为3 3 0,最终陷入死锁,

只要为在为P4进程的请求资源后的剩余资源足够其他进程的最低要求为1 0 1,便可以有效避免死锁现象的产生。

六 、实验体会

加深了对死锁概念的理解,能够利用银行家算法,有效避免死锁的发生,或检测死锁的存在。对进程之间的运行情况有了更加深层次的理解
重复不断的实验中,最终感受:实验源码存在不足;

  1. 实验一直在循环,不能自动停止
  2. 实验的资源不能收回,其实不是不能回收,是回收之后,并没有在输出部分显示出来,因此,给人误导,资源不够的感觉,所以,在这个部分可以适当修改。
    通过这个实验,对于死锁的理解更加透彻,并且印象变得深刻了,接下来,会对源码进行一定的修改,努力地解决以上两个问题的存在。
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值