多线程(进程)中死锁的产生和如何避免死锁

死锁

由于两个或者两个以上的(进程)去抢夺一份资源而造成阻塞的状态叫做死锁,
如果出现了死锁,会造成线程的循环等待,如果没有外力的帮助,就会一直维持着某种状态

死锁的产生

死锁的产生有如下四个必要条件
      1. 资源是互斥的,同一时刻只能有一个进程占有该资源
      2. 资源的释放只能有该进程自己完成
      3. 线程在获取到需要资源之前,不会释放已有资源
      4. 存在这么一条循环等待的队列,线程T1,T2,T3…, Tn
      T1持有自己的资源请求T2的资源,….Tn持有自己的资源请求T1的资源
      

典型的问题例如哲学家饥饿问题,在我另一片博客有提到,感兴趣的话不妨看看:
使用信号量解决哲学家饥饿问题

处理死锁的方式

死锁的预防

其实死锁的4个发生条件都是必要条件,也就是说4个条件缺一不可,我们可以通过破坏其中任意一个条件来预防死锁
#### 1.破坏资源的互斥性
这是不可能滴,在访问临界资源时,至少要保证对资源的访问是互斥的,例如一台打印机在任意一时刻只能打印一个文件

2.破坏不可抢占的条件

允许其他资源对资源的抢夺
方案 1.在该方案下,如果占有某些资源的进程在进一步申请资源被拒绝后,就必须释放原本占有的资源,如果有必要,则可以再次申请这些资源或者另外资源

方案 2. 如果一个进程请求当前被另一个进程占有的资源,则操作系统可以抢占另一个进程,要求它释放资源.当然这必须是在两个不同优先级的进程才能生效

3.破坏请求和保持条件

在系统中不允许进程在已获得某种资源的情况下,申请其他资源.即阻止进程在持有资源的同时申请资源

方案 1. 所有进程在运行之前,必须一次性地申请在整个运行过程中所需的全部资源,在运行期间不能申请资源,带来的问题是

a.假设一个进程需要多种类型的资源,其中只有一组不满足进程所需,其他资源也必须保持空闲状态,严重影响资源的利用率
b.会使某些进程长期得不到资源而发生饥饿问题,例如解决哲学家就餐问题时,我那篇文章就采用的是此方案,每个哲学家同时申请两个筷子,否则就等待,有可能某些哲学家长期不能一次申请到两个筷子而饿死….

方案2 要求每个进程在申请资源时,同时放弃已占有的资源,即使可能该进程很快又需要此资源
当然这中方案也不是完全可以避免死锁 假设两个哲学家两个筷子,每个哲学家都拿着一个筷子,在申请对方筷子时又释放掉自己的筷子,就会又陷入死锁

4.破坏循环等待条件

将系统中的所有资源统一编号,进程可在任何时刻提出申请资源,但申请必须按资源的顺序提出,例如 1只能申请2号的资源,2号不能申请1号的资源

经典的银行家算法

有5个向量
Max:表示线程对每类资源的最大需求量;

Allocation:表示系统给线程已分配每类资源的数目;

Need:表示线程还需各类资源数目;

Available:表示系统当前剩下的资源。

当一个线程发出request时,先看request[i]是否小于其需求need 如果小于则
进入查看request是否小于当前系统剩余总量Available ,如果满足则 暂时修改当前工作状态

Max-=request

Allocation+=request

Need-=request

Available-=request

然后进行安全检测 :
设置一个工作向量 work = 此刻的Available
查看剩余的进程是否有仍未完成的资源
finish = flase

而且其所需资源(Need) < work(当前肾剩余资源)

若找到就将资源费配给他

等它运行完毕后就会释放资源,此时
work = 之前剩余的work + 此进程运行时的资源MAX

之后当所有
finish = flase 的资源都可以获得所需资源而运行完
则表示此次分配是安全的,就可以分配

若不能满足上述条件,则表明此次分配是不安全的 就撤回其申请.

安全算法的原因

本质: 当我给你这个进程分配资源以后

要保证我剩余的资源能够在 剩下的进程中周转开来

例如 给 1分配资源后 ,剩下3个进程都开始申请资源

假设剩下三个进程ID 为 A, B ,C

假设ABC三个人的状态都是flase
给进程1分配资源后,剩余资源为 available
一直轮询 ABC 剩下的资源你们谁能完全利用,完成你们的事情, 然后后把你们占有的所有资源都归回来

假设A 发现剩下的资源他可以利用, (need < available )
那么它干完事情后就把它资源全部归还

此时剩下的资源就是 available + alloctoin(A)

再去轮询 看剩下 B和C是否能够完成 他们的事情

当ABC都能完成他们的事情,那么给1分配他所需的资源才是合理的 (此时成为安全序列)
因为总(存在一种分配方案使 ABC都可以完成任务的分配 )
若不满足以上的检查,分配出去以后就是不安全序列 ,有可能就会发生死锁

eg:

假如第一个进程获得 所需资源 后,释放的资源和剩余的资源加起来不能满足以后所有进程中任何一个的需求量 剩下所有进程都会去占有资源而无法运行完,就不会去释放资源,
就会造成进程的死锁问题

你可能感兴趣的:(多线程(进程)中死锁的产生和如何避免死锁)