目录
-
死锁的概念
-
阐述死锁的概念、产生的原因及产生死锁的必要条件;
-
解决死锁的常见办法或措施;
-
预防死锁
以哲学家就餐问题,分析和阐述预防哲学家就餐时发生死锁几种实现方法;
哲学家问题
主要是互斥问题,假设有5个哲学家,只有同时持有两个筷子(临界资源)才能吃饭(运行)
如果每个哲学家都拿起筷子,那么每个哲学家只有一个筷子,出现死锁现象。
防止死锁方法
1.增加限制:允许最多四个哲学家同时进餐。
2.要求奇数位的哲学家先拿左边的筷子,然后再拿右边的筷子,而偶数哲学家正好相反。
3.仅当一个哲学家左右两支筷子都可用时才允许他抓起来筷子。
(伪代码)
semaphore chopstick[5]={1,1,1,1,1}
semaphore mutex=1;
pi(){
while(1){
p(mutex);
p(chopstick[i]);
p(chopstick[i+1]%5);
v(mutex);
吃饭
v(chopstick[i]);
v(chopstick[i+1]%5);
思考
}
}
当p1运行到p(mutex);时,其他进程不能运行,只有p1得到两个资源,运行v(mutex);其他进程才能运行。这样实现了多个进程互斥的访问两个资源。
-
避免死锁:银行家算法
核心思想:在进程提出资源申请时,先预判此次分配是否导致系统进入不安全状态,如果导致不安全状态,就暂时不答应这次请求,让该进程先阻塞等待。
下面是流程图
安全状态(存在安全序列):指的是资源请求得到分配后,能找到一条通路,完成其他进程的需求,不至于其他进程得不到资源,造成死锁。
实验所用到数据以及定义代码,如下所示
static int[][] max; //最大需求
static int[][] allocation;//已分配
static int[][] need; //还需要
static int[] request;//请求
static int[] ava;//剩余资源
按上面流程图,具体实现的代码。
for(int j=0;j<3;j++)
if(request[j]>need[i][j]) {//判断请求是否合理错误
System.out.println("出错");
return;
}
for(int j=0;j<3;j++)//判断剩余资源是否满足要求
if(ava[j]<request[j]) {
System.out.println("进程:"+i+"等待");
return;
}
if(request[0]==need[i][0]&&request[1]==need[i][1]&&request[2]==need[i][2])boo=true;
for(int j=0;j<3;j++) {//资源分配
ava[j]-=request[j];
need[i][j]-=request[j];
allocation[i][j]+=request[j];
}
int a=0;
if(boo==true) {
for(int j=0;j<3;j++) {
ava[j]+=allocation[i][j];
}
System.out.print("进程:"+i+"->");
a++;
}
djks(a);//判断资源分配完后是否处于安全序列
其中djks()函数使用迭代的思想。每一次循环都遍历所有的进程。满足条件的进入迭代,直到所有迭代都结束。
public static void djks(int a) {
int k=0;
for(k=0;k<5;k++) {
if(ava[0]<need[k][0]||ava[1]<need[k][1]||ava[2]<need[k][2]) {
continue;
}else if(need[k][0]==0&&need[k][1]==0&&need[k][2]==0) {
}else{
for(int j=0;j<3;j++) {
ava[j]+=allocation[k][j];
need[k][j]=0;
}
System.out.print("\t进程:"+k+"->");
a++;
djks(a);
}
}
if(a==5) {
System.out.println("安全序列");
}
}
-
完整代码
package bank;
import java.util.Scanner;
public class Text {
static int[][] max; //最大需求
static int[][] allocation;//已分配
static int[][] need; //还需要
static int[] request;//请求
static int[] ava;//剩余资源
public static void main(String[] args) {
boolean boo=false;
Scanner scan=new Scanner(System.in);
max=new int[][] { {7,5,3},
{3,2,2},
{9,0,2},
{2,2,2},
{4,3,3}};
allocation=new int[][]{ {0,1,0},
{2,0,0},
{3,0,2},
{2,1,1},
{0,0,2}};
need=new int[][]{ {7,4,3},
{1,2,2},
{6,0,0},
{0,1,1},
{4,3,1}};
System.out.println("进程:");
int i=scan.nextInt();
System.out.println("输入需求:");
request=new int[] {scan.nextInt(),scan.nextInt(),scan.nextInt()};
ava=new int[] {3,3,2};
for(int j=0;j<3;j++)
if(request[j]>need[i][j]) {//判断请求是否合理错误
System.out.println("出错");
return;
}
for(int j=0;j<3;j++)//判断剩余资源是否满足要求
if(ava[j]<request[j]) {
System.out.println("进程:"+i+"等待");
return;
}
if(request[0]==need[i][0]&&request[1]==need[i][1]&&request[2]==need[i][2])boo=true;
for(int j=0;j<3;j++) {//资源分配
ava[j]-=request[j];
need[i][j]-=request[j];
allocation[i][j]+=request[j];
}
int a=0;
if(boo==true) {
for(int j=0;j<3;j++) {
ava[j]+=allocation[i][j];
}
System.out.print("进程:"+i+"->");
a++;
}
djks(a);//判断资源分配完后是否处于安全序列
}
//使用迭代实现
public static void djks(int a) {
int k=0;
for(k=0;k<5;k++) {
if(ava[0]<need[k][0]||ava[1]<need[k][1]||ava[2]<need[k][2]) {
continue;
}else if(need[k][0]==0&&need[k][1]==0&&need[k][2]==0) {
}else{
for(int j=0;j<3;j++) {
ava[j]+=allocation[k][j];
need[k][j]=0;
}
System.out.print("\t进程:"+k+"->");
a++;
djks(a);
}
}
if(a==5) {
System.out.println("安全序列");
}
}
}
-
实验运行结果及分析
五个进程都得到满足,所以存在安全序列