1.什么是死锁?
死锁是指两个或两个以上的进程,由于争夺资源而产生的相互等待的状态。
2.死锁发生的条件?
死锁发生的四个必要条件包括:互斥、不可剥夺、请求和保持、循环等待。
互斥指的是多个进程不能同时获得某项系统资源。
不可剥夺指的是一个进程不能剥夺另一个进程已经占有的系统资源。
请求和保持指的是一个进程会在已经占有某一项系统资源时请求另外的系统资源,而且如果请求得不到满足就不会释放已有资源。
循环等待指的是进程与资源之间会形成请求环路。
3.解决死锁的手段
解决死锁的手段主要包括三大类:鸵鸟算法、不让死锁发生、死锁发生后再处理。
3.1 鸵鸟算法
“鸵鸟算法”其实就是假装不知道死锁的存在,不考虑死锁这一问题。
因为解决死锁的代价比较高昂,所以如果不处理死锁的话,可以获得更高的性能。
如果死锁发生之后对用户的影响很小,或者死锁发生的概率很小,那么就可以考虑忽略死锁。
主流的操作系统Linux和Windows处理死锁的策略都是鸵鸟算法。
3.2 不让死锁发生
不让死锁发生,就是把措施做在前面,包括了两种方法:基于静态策略的死锁预防和基于动态策略的死锁避免。
3.2.1 死锁预防
死锁预防的主要思路是破坏四个必要条件之一,其中互斥条件一般没法破坏,所以就有了以下几种死锁防止的方法:
- 为了破坏不可剥夺条件,可以将资源属性设置为可剥夺,高优先级进程在申请低优先级进程占有资源时,可以强制让低优先级进程释放,这种方法适用于任意两个进程的优先级都不同的情况。
- 为了破坏请求和保持条件,可以一次性将某个进程需要的所有资源都分配到位,这样就破坏了“请求”条件,但凡有一种资源请求无法得到满足,那么该进程都需要等待,这样就破坏了“保持”条件。
- 为了破坏循环等待条件,可以将所有类型的资源都进行编号,进程在请求资源时必须按照指定编号的顺序请求。
3.2.2 死锁避免
死锁避免的主要手段是通过银行家算法。银行家算法的基本思想是分配资源之前,先进行试分配并判断系统是否是安全的,如果是才真正分配。
算法运行过程中主要涉及2个矩阵和1个向量:
现有可用资源向量available
分配矩阵allocated
需求矩阵need
算法流程:
判断请求是否不大于need对应行、是否不大于available,如果是,则将资源进行尝试分配,更新available、need和allocated,运行安全性检查算法,如果系统处于安全状态则分配成立、进行真正的分配操作,否则分配失败、等待。
安全性检查算法中设置了work向量,初值为available,并为每个进程设置标志位finish,初始值都设置为false,每次寻找一个finish为false且对应行need<=work的进程,尝试分配,并释放现有资源,将finish设置为true,work加上对应行的allocated,直到全部进程finish均为true或找不到符合条件的进程为止,如果最后所有进程finish均为true,则系统是安全的,否则是不安全的。
3.3 死锁发生后再处理
死锁发生后解除的方法包括:
- 杀掉造成死锁的进程,释放它所占有的系统资源。
- 从一个或多个进程中抢占资源,分配给死锁进程,以让其需求得到满足从而释放占有资源。