预防和避免死锁的方法及银行家算法的java简单实现

时间:2022-08-22 04:04:47

  • 预防死锁

    (1) 摒弃“请求和保持”条件

    基本思想:规定所有进程在开始运行之前,要么获得所需的所有资源,要么一个都不分配给它,直到所需资源全部满足才一次性分配给它。

    优点:简单、易于实现且很安全

    缺点:资源被严重浪费,进程延迟运行

    (2) 摒弃“不剥夺”条件

    基本思想:当一个已经保持了某些资源的进程,再提出新的资源请求而不能立即得到满足时,必须释放它已经保持了的所有资源,待以后需要时再重新申请。这意味着某一进程已经占有的资源,在运行过程中会被暂时地释放掉,也可认为是被剥夺了,从而摒弃了“不剥夺”条件。

    (3) 摒弃“环路等待”条件

    基本思想:系统将所有资源按类型进行线性排队,并赋予不同的序号,所有进程对资源的请求必须严格按照资源序号递增的次序提出。由于只允许在保持高顺位资源的情况下申请低顺位资源,不允许在保持低顺位资源的情况下申请高顺位资源,因此环路等待条件被破坏。
  • 避免死锁

    (1) 系统的安全状态

    所谓安全状态,是指系统能按某种进程顺序(P1,P2,…,Pn),来为每个进程Pi分配其所需资源,直至满足每个进程对资源的最大需求,使每个进程都可顺利地完成,称系统处于安全状态, 称〈P1,P2,…,Pn〉序列为安全序列 。如果系统无法找到这样一个安全序列,则称系统处于不安全状态。

    安全状态,一定不会死锁;

    不安全状态不必然死锁;

    避免死锁的实质在于:系统在进行资源分配时,如何避免系统不进入不安全状态。

    (2) 利用银行家算法避免死锁

    一、进程向操作系统请求分配资源相当于用户银行贷款,为保证资金安全:

    ①当一个顾客对资金的最大需求量不超过银行家现有的资金就可以接纳该顾客;

    ②顾客可以分期贷款,但总数不能超过最大需求

    ③银行家现有资金不满足顾客,可以推迟,但顾客会在有限时间内获得贷款

    ④顾客得到全部资金后会在有限时间内归还。

    二、从操作系统角度来看:

    进程首次申请资源,系统现存资源>线程最大资源需求时分配,否则延迟;

    进程执行期间,进程本次申请的资源数<系统剩余资源数,分配,否则延迟.

    三、举个栗子

    假定系统中有五个进程{P0,P1,P2,P3,P4}和三类资源{A,B,C},各种资源的数量分别为10、5、7,在T0时刻的资源分配情况如下:

    预防和避免死锁的方法及银行家算法的java简单实现

    存在安全序列:

    (P1,P3,P4,P0,P2) OR (p1 p3 p0 p2 p4)
  • 银行家算法的java简单实现

    ①首先创建一个用户类
/*
* 用户类
*/
public class Person { //用户名字
private String name;
//用户所需最大资源数
private int[] max;
//用户现有资源数
private int[] allocation;
//用户所需资源数
private int[] need;
//用户请求资源数,本实例中请求数require等于need所需资源数
private int[] require; public Person(String name) {
this.name = name;
}
@Override
public String toString() {
// TODO Auto-generated method stub
return name;
} public void setMax(int[] max) {
this.max = max;
System.out.println(name + "最大资源需求");
for(int i = 0; i < max.length; i++) {
System.out.print(i + ":" + max[i] + " ");
}
System.out.println();
} public int[] getMax() {
return max;
} public int[] getAllocation() {
return allocation;
} public void setAllocation(int[] allocation) {
this.allocation = allocation;
System.out.println(name + "当前拥有资源");
for(int i = 0; i < allocation.length; i++) {
System.out.print(i + ":" + allocation[i] + " ");
}
System.out.println();
} public int[] getNeed() {
return need;
} public void setNeed() {
int[] need1 = new int[max.length];
for(int i = 0; i < max.length; i++) {
need1[i] = max[i] - allocation[i];
}
this.need = need1;
System.out.println(name + "所需资源");
for(int i = 0; i < need.length; i++) {
System.out.print(i + ":" + need[i] + " ");
}
System.out.println();
} public int[] getRequire() {
return require;
} public int[] setRequire() {
this.require = need;
System.out.println(name + "发起请求");
for(int i = 0; i < require.length; i++) {
System.out.print(i + ":" + require[i] + " ");
}
System.out.println("");
System.out.println("----------");
return require;
} }

②创建银行家类并进行测试

public class BlankTest {

	//list1中存储竞争资源的用户
public static ArrayList<Person> list1 = new ArrayList<>();
//list2已经完成的用户
public static ArrayList<Person> list2 = new ArrayList<>();
//银行家现有资源
public static int[] avaiable = new int[3];
/*
* 是否可以分配,即请求是否小于系统现有资源
*/
public static boolean CanRequired(int[] avaiable, int [] require) {
for(int i = 0; i < avaiable.length; i++) {
if(avaiable[i] < require[i]) {
return false;
}
}
return true;
}
/*
* 分配动作
*/
public static void send(int[] avaiable, int [] allocation) { System.out.println("系统现有资源");
for(int j = 0; j < avaiable.length; j++) {
avaiable[j] = avaiable[j] + allocation[j];
System.out.print(avaiable[j] + " ");
}
System.out.println();
}
/*
* 初始化数据和测试
*/
public static void main(String[] args) {
//初始化资源
avaiable[0] = 3;
avaiable[1] = 3;
avaiable[2] = 2;
int[] max1 = new int[3];
max1[0] = 7;
max1[1] = 5;
max1[2] = 3;
int[] allocation1 = new int[3];
allocation1[0] = 0;
allocation1[1] = 1;
allocation1[2] = 0;
Person p0 = new Person("p0");
p0.setMax(max1);
p0.setAllocation(allocation1);
p0.setNeed();
int[] max2 = new int[3];
max2[0] = 3;
max2[1] = 2;
max2[2] = 2;
int[] allocation2 = new int[3];
allocation2[0] = 2;
allocation2[1] = 0;
allocation2[2] = 0;
Person p1 = new Person("p1");
p1.setMax(max2);
p1.setAllocation(allocation2);
p1.setNeed();
int[] max3 = new int[3];
max3[0] = 9;
max3[1] = 0;
max3[2] = 2;
int[] allocation3 = new int[3];
allocation3[0] = 3;
allocation3[1] = 0;
allocation3[2] = 2;
Person p2 = new Person("p2");
p2.setMax(max3);
p2.setAllocation(allocation3);
p2.setNeed();
int[] max4 = new int[3];
max4[0] = 2;
max4[1] = 2;
max4[2] = 2;
int[] allocation4 = new int[3];
allocation4[0] = 2;
allocation4[1] = 1;
allocation4[2] = 1;
Person p3 = new Person("p3");
p3.setMax(max4);
p3.setAllocation(allocation4);
p3.setNeed();
int[] max5 = new int[3];
max5[0] = 4;
max5[1] = 3;
max5[2] = 3;
int[] allocation5 = new int[3];
allocation5[0] = 0;
allocation5[1] = 0;
allocation5[2] = 2;
Person p4 = new Person("p4");
p4.setMax(max5);
p4.setAllocation(allocation5);
p4.setNeed();
System.out.println();
list1.add(p0);
list1.add(p1);
list1.add(p2);
list1.add(p3);
list1.add(p4);
//index用于记录每趟循环是否有用户得到资源,没有说明不存在安全序列,结束分配
int index = 0;
//开始分配
for(int x = 0; x < list1.size(); x++) {
if(index != x) {
System.out.println("找不到安全队列");
break;
}
for(int z = 0; z < list1.size(); z++) {
/*
* 判断请求资源是否小于系统现有资源,并且该用户需要满足不在安全序列中,这里的请求是简单的一次请求
*/
if(CanRequired(avaiable, list1.get(z).setRequire()) && !list2.contains(list1.get(z))) {
System.out.println("该请求得到响应");
index++;
send(avaiable, list1.get(z).getAllocation());
list2.add(list1.get(z));
break;
} }
}
System.out.println();
for(Person p: list2) {
System.out.print(p + " ");
} }
}

③测试结果

初始化资源

预防和避免死锁的方法及银行家算法的java简单实现

分配

预防和避免死锁的方法及银行家算法的java简单实现

最终结果

预防和避免死锁的方法及银行家算法的java简单实现