死锁的解决方法

产生死锁的必要条件?

死锁的产生是必须要满足一些特定条件的:
• 互斥条件:某资源只能被一个进程使用,其他进程请求该资源时,只能等待,直到资源使用完毕后释放资源。
• 请求和保持条件:程序已经保持了至少一个资源,但是又提出了新要求,而这个资源被其它进程占用,自己占用资源却保持不放。
• 不剥夺条件:任何一个资源在没被该进程释放之前,任何其他进程都无法对他剥夺占用。
• 循环等待条件:当发生死锁时,所等待的进程必定会形成一个环路(类似于死循环),造成永久阻塞。

处理死锁思路?

• 预防死锁:破坏死锁的四个条件中的一个或多个来预防死锁。但不能破坏互斥条件,其他三个都可。
• 避免死锁:和预防死锁的区别就是,在资源动态分配过程中,用某种方式阻止系统进入不安全状态。比如银行家算法。
• 检测死锁:允许系统在运行过程中发生死锁,但可已设置检测机构及时检测死锁的发生,并采取适当措施加以清除。
• 解除死锁:发生死锁后,采取适当措施将进程从死锁状态中解脱出来。解除死锁主要方法:资源剥夺法,撤销进程法,进程回退法。

预防死锁的方法:

破坏请求和保持条件: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;
} 
  • 11
    点赞
  • 50
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
MySQL死锁是指两个或多个事务互相等待对方释放资源而无法继续执行的情况。解决MySQL死锁方法有以下几种: 1. 重试机制:当检测到死锁发生时,可以选择在一段时间后重新尝试执行事务。这样可以避免长时间的等待并解除死锁。 2. 锁超时机制:为每个事务设置一个合理的超时时间。当一个事务在超过设定的超时时间后仍然未能获取到所需的锁,可以选择回滚该事务并释放已获取的资源,以避免死锁的发生。 3. 优化事务并发性:通过合理的事务设计和数据库结构优化,可以减少事务之间的冲突,从而降低死锁的发生率。 4. 调整锁粒度:根据具体情况,可以将锁的粒度调整为表级锁或页级锁,以减少死锁的可能性。但需要注意的是,锁粒度的调整应该是在权衡并发性和数据完整性之间做出的合理选择。 5. 分析并解决死锁:当死锁发生时,可以通过MySQL提供的一些工具和命令来分析死锁的原因,找出造成死锁的具体事务和资源,并进行相应的解决措施,例如撤销某个事务或修改事务执行顺序等。 需要注意的是,不同存储引擎对死锁的处理方式可能会有所不同。因此,在解决MySQL死锁问题时,需要根据具体的存储引擎来选择合适的解决方法。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [mysql数据库死锁问题处理](https://blog.csdn.net/zy103118/article/details/124823532)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值