产生死锁的必要条件?
死锁的产生是必须要满足一些特定条件的:
• 互斥条件:某资源只能被一个进程使用,其他进程请求该资源时,只能等待,直到资源使用完毕后释放资源。
• 请求和保持条件:程序已经保持了至少一个资源,但是又提出了新要求,而这个资源被其它进程占用,自己占用资源却保持不放。
• 不剥夺条件:任何一个资源在没被该进程释放之前,任何其他进程都无法对他剥夺占用。
• 循环等待条件:当发生死锁时,所等待的进程必定会形成一个环路(类似于死循环),造成永久阻塞。
处理死锁思路?
• 预防死锁:破坏死锁的四个条件中的一个或多个来预防死锁。但不能破坏互斥条件,其他三个都可。
• 避免死锁:和预防死锁的区别就是,在资源动态分配过程中,用某种方式阻止系统进入不安全状态。比如银行家算法。
• 检测死锁:允许系统在运行过程中发生死锁,但可已设置检测机构及时检测死锁的发生,并采取适当措施加以清除。
• 解除死锁:发生死锁后,采取适当措施将进程从死锁状态中解脱出来。解除死锁主要方法:资源剥夺法,撤销进程法,进程回退法。
预防死锁的方法:
破坏请求和保持条件:1、一次性申请所有资源,之后不再申请资源,如果不满足资源条件则得不到资源分配。2、只获得初期资源运行,之后将运行完的资源释放,请求新的资源。
破坏不可剥夺条件:当一个进程获得某种不可抢占资源,提出新的资源申请,若不能满足,则释放所有资源,以后需要,再次重新申请。
破坏循环等待条件:对进程进行排号,按照序号递增的顺序请求资源。若进程获得序号高的资源想要获取序号低的资源,就需要先释放序号高的资源。
避免死锁的方法:
银行家算法
我们可以把操作系统看做是银行家,操作系统管理的资源相当于银行家管理的资金,进程向操作系统请求分配资源相当于客户向银行家申请贷款。
为保证资金的安全,银行家规定:
1. 当一个客户对资金的最大需求量不超过银行家现有的资金时就可以接纳该用户;
2. 客户可以分期贷款,但贷款的总数不能超过最大需求量;
3. 当银行家现有的资金不能满足客户需求的贷款数额时,对客户的贷款可推迟支付,但总能使客户在有限的时间里得到贷款;
4. 当客户得到所需的全部资金后,一定能在有限的时间里归还所有的资金。
操作系统按照银行家指定的规则为进程分配资源,当进程首次申请资源时,要测试该进程对资源的最大需求量,如果系统现存的资源可以满足它的最大需求量,则按当前的申请量分配资源,否则就推迟分配,当进程在执行中继续申请资源时,先测试该进程本次申请的资源数是否超过了该资源所剩余的总量,若超过则拒绝分配进程,若能满足则按当前的申请量分配资源,否则也要推迟分配。
解除死锁的方法:
1.资源剥夺:挂起某些死锁进程,并抢占它的资源,讲这些资源分配给其他的死锁进程。但应防止被挂起的进程长时间得不到进程,而处于资源匮乏状态。
2. 终止(撤销)进程:强制将一个或多个死锁进程终止(撤销)并剥夺这些进程的资源,直至打破循环环路,使系统从死锁状态中解脱出来。撤销的原则可以按照进程的优先级和撤销进程代价的高低进行。
进程回退:让一个或多个进程回退到足以避免回避死锁的地步,进程回退时资源释放资源而不是被剥夺。要求系统保持进程的历史信息,设置还原点。
银行家算法代码:
#include<bits/stdc++.h>
using namespace std;
const int M=5; // 进程数
const int N=3; // 资源数
// 最大需求矩阵 m*n矩阵定义m个进程对n类资源的最大需求量
int Max[M][N]={{7,5,3},{3,2,2},{9,0,2},{2,2,2},{4,3,3}};
// 可用资源向量 长度为n的数组表示系统中n类资源的当前可用数目
int Available[N]={3,3,2};
// 已分配资源矩阵 m*n矩阵定义了每个进程现在已分配到的各类资源的实际数目
int Allocation[M][N]={{0,1,0},{2,0,0},{3,0,2},{2,1,1},{0,0,2}};
// 需求矩阵 m*n矩阵表示每个进程还需要的各类资源的数目
int Need[M][N]={{7,4,3},{1,2,2},{6,0,0},{0,1,1},{4,3,1}};
int Request[N]={0,0,0};
// 当前资源分配情况
void show(){
int i,j;
cout<<"系统可用的资源数为:"<<endl;
for(j=0;j<N;j++){
cout<<"资源"<<j<<": "<<Available[j]<<" \n";
}
cout<<endl;
cout<<"各进程还需要的资源量:"<<endl;
for (i=0;i<M;i++){
cout<<"进程"<<i<<": ";
for (j=0;j<N;j++){
cout<<"资源"<<j<<": "<<Need[i][j]<<" ";
}
cout<<endl;
}
cout<<endl;
cout<<"各进程已经得到的资源量:"<<endl;
for (i=0;i<M;i++){
cout<<"进程"<<i<<": ";
for(j=0;j<N;j++){
cout<<"资源"<<j<<": "<<Allocation[i][j]<<" ";
}
cout<<endl;
}
}
int find(int Work[],bool Finish[]){
for(int i=0;i<M;++i){
bool flag=true;
if(Finish[i]==false){
for(int j=0;j<N;++j){
if(Need[i][j]>Work[j]){
flag=false;
}
}
}else{
continue;
}
if(flag){
return i;
}
}
return -1;
}
bool check(){
int Work[N]={Available[0],Available[1],Available[2]};
bool Finish[M]={false};
while(1){
int i=find(Work,Finish);
if(i==-1){
break;
}
// 进程Pi释放所占的全部资源
for(int j=0;j<N;++j){
Work[j]+=Allocation[i][j];
}
Finish[i]=true;
}
for(int i=0;i<M;++i){
if(Finish[i]!=true){
return false;
}
}
return true;
}
void requestAndAlloc(){
int k;
cout<<"\n请输入请求进程: ";
cin>>k;
if(k==-1){
exit(0);
}
memset(Request,0,sizeof(Request));
cout<<"请输入N中资源的请求数量: ";
for(int j=0;j<N;++j){
cin>>Request[j];
}
for(int j=0;j<N;++j){
if(Request[j]>Need[k][j]){
cout<<"进程Pi对资源的请求量已超过其说明的最大数量";
return;
}
if(Request[j]>Available[j]){
cout<<"系统现在没有可用的资源,进程k必须等待\n";
return;
}
}
// 系统给进程k分配所请求的资源
for(int j=0;j<N;++j){
Available[j]-=Request[j];
Allocation[k][j]+=Request[j];
Need[k][j]-=Request[j];
}
if(!check()){
cout<<"无法完成请求"<<endl;
for(int j=0;j<N;++j){
Available[j]+=Request[j];
Allocation[k][j]-=Request[j];
Need[k][j]+=Request[j];
}
}else{
cout<<"请求完成\n\n\n";
show();
}
}
int main(){
cout<<"如果输入请求进程进程编号为-1,则退出本程序\n";
cout<<"如果输入请求进程进程编号为-1,则退出本程序\n";
cout<<"如果输入请求进程进程编号为-1,则退出本程序\n\n";
show();
while(1){
requestAndAlloc();
}
return 0;
}