您的位置:首页 > 其它

死锁的产生、解除与预防

2012-10-03 19:13 155 查看
死锁是指两个或两个以上的进程在执行的过程中,因争夺资源而造成的一种互相等待的现象。

产生死锁的四个必要条件:

1、互斥条件:一个资源每次只能被一个进程使用。

2、请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。(资源的部分分配)

3、不剥夺条件:进程已经获得的资源,在未使用完之前,不能强行剥夺。

4、循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。

上述四个条件是产生死锁的四个必要条件,只要上述四个之中有一个不满足,就不会发生死锁。

根据上述条件,列出三条预防措施:

1、采用资源静态分配的策略,破坏“部分分配”条件。

2、允许进程剥夺使用其他进程占有的资源,从而破坏“不可剥夺”条件。

3、采用资源有序分配方法,破坏“环路”条件。

注意:互斥条件没法被破坏。

死锁避免算法里最著名的算法就是Dijkstra的银行家算法。

银行家算法:

基本思想是分配资源之前,判断系统是否是安全的;若是,才分配。它是最具有代表性的避免死锁的算法。

  设进程cusneed提出请求REQUEST [i],则银行家算法按如下规则进行判断。

  (1)如果REQUEST [cusneed] [i]<= NEED[cusneed][i],则转(2);否则,出错。

  (2)如果REQUEST [cusneed] [i]<= AVAILABLE[cusneed][i],则转(3);否则,出错。

  (3)系统试探分配资源,修改相关数据:

  AVAILABLE[i]-=REQUEST[cusneed][i];

  ALLOCATION[cusneed][i]+=REQUEST[cusneed][i];

  NEED[cusneed][i]-=REQUEST[cusneed][i];

  (4)系统执行安全性检查,如安全,则分配成立;否则试探险性分配作废,系统恢复原状,进程等待。

安全性检查算法:

  (1)设置两个工作向量Work=AVAILABLE; FINISH(全为false)

  (2)从进程集合中找到一个满足下述条件的进程,

  FINISH==false;

  NEED<=Work;

  如找到,执行(3);否则,执行(4)

  (3)设进程获得资源,可顺利执行,直至完成,从而释放资源。

  Work+=ALLOCATION;

  Finish=true;

  GOTO(2)

  (4)如所有的进程Finish= true,则表示安全;否则系统不安全。

银行家算法的代码实例:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define N 5  //进程个数
#define M 3  //资源种类

int main()
{
int i,j;
int a;
int Request[M];//请求资源距阵
int Allocation
[M];//已经分配资源矩阵
int Need
[M];//需求矩阵
int Available[M];//可利用资源量

//输入已经分配的资源
printf("请输入已经分配的资源:\n");
for(i=0;i<N;i++)
{
printf("请输入第 %d 个进程已经分配的资源:",i+1);
for(j=0;j<M;j++)
scanf("%d",&Allocation[i][j]);
}

//输入各个进程还需要的资源
printf("\n请输入各个进程还需要的资源:\n");
for(i=0;i<N;i++)
{
printf("请输入第 %d 个进程还需要的资源:",i+1);
for(j=0;j<M;j++)
scanf("%d",&Need[i][j]);
}

//输入可以利用的资源数据
printf("\n请输入可以利用的资源数据:");
for(i=0;i<M;i++)
scanf("%d",&Available[i]);

while(1)
{
start:printf("\n\n请输入是第几个进程发出资源请求:");
scanf("%d",&a);//输入的是第几个进程的请求
printf("\n第 %d 个进程资源请求数:",a);
for(i=0;i<M;i++)
scanf("%d",&Request[i]);

//银行家算法第一步
for(i=0;i<M;i++)
{
if(!(Request[i]<=Need[a-1][i]))
{
printf("P%d 非法请求!",a);
printf("不可以分配给 P%d 进程!",a);
goto start;
}
}

//银行家算法第二步
for(i=0;i<M;i++)
{
if(!(Request[i]<=Available[i]))
{
printf("P%d 进程阻塞!",a);
printf("不可以分配给 P%d 进程!",a);
goto start;
}
}

//银行家算法第三步:试探性分配
for(i=0;i<M;i++)
{
Available[i]=Available[i]-Request[i];
Allocation[a-1][i]=Allocation[a-1][i]+Request[i];
Need[a-1][i]=Need[a-1][i]-Request[i];
}

//银行家算法第四步:安全性检查
int Finish
={0,0,0,0,0};
int Work[M];
for(i=0;i<M;i++)
Work[i]=Available[i];

int flag=1;

while(flag==1)
{
for(i=0;i<N;i++)
{
for(j=0;j<M;j++)
{
if(Finish[i]==0 && Need[i][j]<=Work[j])
{
if(j==M-1)
{
Finish[i]=1;
printf("\nP%d 进程安全性检查通过",i+1);
for(j=0;j<M;j++)
Work[j]=Work[j]+Allocation[i][j];
}
}
continue;
}
}
int sum=0;
for(i=0;i<N;i++)
sum=sum+Finish[i];
if(sum==5)
flag=0;

}

for(i=0;i<N;i++)
{
if(Finish[i]==0)
{
printf("试探性分配不成功!安全性检查不通过!");
printf("\n不可以分配给 P%d 进程!",a);
Available[i]=Available[i]+Request[i];
Allocation[a-1][i]=Allocation[a-1][i]-Request[i];
Need[a-1][i]=Need[a-1][i]+Request[i];
goto start;
}
}

printf("\n\n安全!可以分配给 P%d 进程!\n",a);

//输出分配成功后资源占有、需求和可利用情况

printf("\n资源占有情况:\n");
for(i=0;i<N;i++)
{
printf("P%d 个进程已经分配的资源:",i+1);
for(j=0;j<M;j++)
printf(" %d ",Allocation[i][j]);
printf("\n");
}

printf("\n资源需求情况:\n");
for(i=0;i<N;i++)
{
printf("P%d 个进程还需要的资源:",i+1);
for(j=0;j<M;j++)
printf(" %d ",Need[i][j]);
printf("\n");
}

printf("\n可以利用的资源数据:");
for(i=0;i<M;i++)
printf(" %d ",Available[i]);

printf("\n");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: