避免死锁的几种方式

避免死锁的几种方式:
设置加锁顺序

设置加锁时限

死锁检测

设置加锁顺序(线程按照一定的顺序加锁):
死锁发生在多个线程需要相同的锁,但是获得不同的顺序。

假如一个线程需要锁,那么他必须按照一定得顺序获得锁。 
例如加锁顺序是A->B->C,现在想要线程C想要获取锁,那么他必须等到线程A和线程B获取锁之后才能轮到他获取。(排队执行,获取锁)

缺点: 
按照顺序加锁是一种有效的死锁预防机制。但是,这种方式需要你事先知道所有可能会用到的锁,并知道他们之间获取锁的顺序是什么样的。

设置加锁时限:(超时重试)
在获取锁的时候尝试加一个获取锁的时限,超过时限不需要再获取锁,放弃操作(对锁的请求。)。

若一个线程在一定的时间里没有成功的获取到锁,则会进行回退并释放之前获取到的锁,然后等待一段时间后进行重试。在这段等待时间中其他线程有机会尝试获取相同的锁,这样就能保证在没有获取锁的时候继续执行比的事情。

缺点: 
但是由于存在锁的超时,通过设置时限并不能确定出现了死锁,每种方法总是有缺陷的。有时为了执行某个任务。某个线程花了很长的时间去执行任务,如果在其他线程看来,可能这个时间已经超过了等待的时限,可能出现了死锁。

在大量线程去操作相同的资源的时候,这个情况又是一个不可避免的事情,比如说,现在只有两个线程,一个线程执行的时候,超过了等待的时间,下一个线程会尝试获取相同的锁,避免出现死锁。但是这时候不是两个线程了,可能是几百个线程同时去执行,大的基数让事件出现的概率变大,假如线程还是等待那么长时间,但是多个线程的等待时间就有可能重叠,因此又会出现竞争超时,由于他们的超时发生时间正好赶在了一起,而超时等待的时间又是一致的,那么他们下一次又会竞争,等待,这就又出现了死锁。

死锁检测:
当一个线程获取锁的时候,会在相应的数据结构中记录下来,相同下,如果有线程请求锁,也会在相应的结构中记录下来。当一个线程请求失败时,需要遍历一下这个数据结构检查是否有死锁产生。

例如:线程A请求锁住一个方法1,但是现在这个方法是线程B所有的,这时候线程A可以检查一下线程B是否已经请求了线程A当前所持有的锁,像是一个环,线程A拥有锁1,请求锁2,线程B拥有锁2,请求锁1。 
当遍历这个存储结构的时候,如果发现了死锁,一个可行的办法就是释放所有的锁,回退,并且等待一段时间后再次尝试。

缺点: 
这个这个方法和上面的超时重试的策略是一样的。但是在大量线程的时候问题还是会出现和设置加锁时限相同的问题。每次线程之间发生竞争。 
还有一种解决方法是设置线程优先级,这样其中几个线程回退,其余的线程继续保持着他们获取的锁,也可以尝试随机设置优先级,这样保证线程的执行。

参考引用:http://ifeve.com/deadlock-prevention/

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
操作系统实验二报告 一.实验名称:死锁的检测与解除 二.实验目的:观察死锁产生的条件,并使用适当的算法,有效的防止避免死锁的发 生。 三.实验内容: 死锁的检测算法: 1.找出不再申请资源的进程,将它们所占的资源与系统中还剩余的资源加在一起作 为"可分配的资源",同时对这些进程置标志; 2.检测所有无标志的进程,找出一个所需资源量不超过"可分配的资源"量的进程, 将其所占用的资源添加到"可分配的资源"中,同时为该进程置标志;重复2)直到所有进 程均有标志或无标志的进程的所需资源量均超过"可分配的资源"量; 3.若进程均有标志,说明系统当前不存在死锁;若存在无标志的进程,则表示系统 当前已有死锁形成,这些无标志的进程就是一组处于死锁状态的进程。 死锁的解除: 当死锁检测程序检测到有死锁存在时,一般采用两种方式来解除死锁: 1.终止进程:终止一个或多个涉及死锁的进程的执行,收回它们所占的资源再分配 。 2.抢夺资源:从涉及死锁的一个或几个进程中抢夺资源,把夺来的资源再分配给卷 入死锁的其他进程,直到死锁解除。 四.实验代码: #include <iostream> using namespace std; #define mp 50 //最大进程数 #define mr 100 /最大资源数 int keyong[mr]; //可用资源数组 int MAX[mp][mr]; //最大需求矩阵 int fenpei[mp][mr]; //分配矩阵 int need[mp][mr]; //剩余需求矩阵 bool FINISH[mp]; //系统是否有足够资源分配 int p[mp]; //记录序列 int Work[mr]; //工作数组 int m,n; //m个进程,n个资源 int l=0; void Init(); //初始化 bool Safe(); void jc(); void main() { Init(); Safe(); if(l!=m) jc();} void Init() //初始化算法 { int i,j; cout<<"请输入进程的数目:"; cin>>m; cout<<"请输入资源的种类:"; cin>>n; cout<<"请输入每个进程最多所需的各资源数,按照"<<m<<"x"<<n<<"矩阵输入"<<endl; for(i=0;i<m;i++) for(j=0;j<n;j++) cin>>MAX[i][j]; cout<<"请输入每个进程已分配的各资源数,也按照"<<m<<"x"<<n<<"矩阵输入"<<endl; for(i=0;i<m;i++) { for(j=0;j<n;j++) { cin>>fenpei[i][j]; need[i][j]=MAX[i][j]-fenpei[i][j]; if(need[i][j]<0) { cout<<"您输入的第"<<i+1<<"个进程所拥有的第"<<j+1<<"个资源数错误,请重新输入:" <<endl; j--; continue; } } } cout<<"请输入各个资源现有的数目:"<<endl; for(i=0;i<n;i++) { cin>>keyong[i]; } cout<<"剩余需求矩阵:"<<endl; for(i=0;i<m;i++) for(j=0;j<n;j++) { cout<<need[i][j]<<" "; if(j==n-1) cout<<endl; } cout<<"各资源现有数量:"<<endl; for(i=0;i<n;i++) cout<<keyong[i]<<" "; cout<<endl; } bool Safe() /*安全性算法*/ { int i,j,k; for(i=0;i<n;i++) Work[i]=keyong[i]; for(i=0;i<m;i++) { FINISH[i]=false; //判断进程i是否已执行 } for(i=0;i<m;i++) { if(FINISH[i]==true) { continue; } else { for(j=0;j<n;j++) { if(need[i][j]>Work[j]) { break; } } if(j==n) { FINISH[i]=true; for(k=0;k<n;k++) { Work[k]+=fenpei[i][k]; //进程i执行完后回收资源} p[l++]=i; i=-1; } else { continue; } } if(l==m) { cout<<"系统是安全的"<<endl; cout<<"安全序列:"<<endl; for(i=0;i<l;i++) { cout<<p[i]; if(i!=l-1) { cout<<"-

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值