死锁
死锁产生的条件
-
互斥 :也就是独享,一个资源在某时刻只能有一个进程使用,具有排他性
-
请求和保持条件:就是拿着碗里想着锅里,在得到一些资源时,同时又在请求其他需求的资源,在其他资源未请求到时,保持等待,不释放已有的资源
-
不可抢占条件:先来后到,进程已获得的资源在使用完之前不能被抢占
-
循环等待:资源等待刚好成环。比如:线程1需要A、B资源 ,线程2需要B、C资源,线程3需要C、A资源。在某一时刻,1拿了A,2拿了B,3拿了C。此时1请求B,2请求C,3请求A,就形成了所有进程都处于等待的死锁状态。
死锁的处理办法
死锁预防
死锁预防:防患于未然,直接破坏死锁产生的条件,这样死
锁也就不会产生了。
-
破坏互斥条件:因为互斥条件时非共享设备所必须的,我们应该保证,所有一般我们不破坏互斥条件。
-
破坏请求和保持条件:请求和保持的要点是线程申请资源总是一部分一部分申请,不完成还不退。所有我们有俩种破坏策略。
第一种是要求线程必须一次申请所有需要的资源,在申请完成后才能开始运行。这种方法缺点还是很明显的,资源浪费现象严重,整个线程的运行过程中所有的资源都不允许别的线程使用,比如在线程运行的早期就已经把晚期的资源给占用了,而使得其他进程无法获取晚期的资源。
第二种是边用边放,早点运行。在获得运行初期的资源就开始运行,并且把用毕的资源释放。 -
破坏不可抢占条件:其实整个策略比较简单,直接规定了线程在新提出的请求资源在未得到满足时,释放已经得到的资源。但是实现很复杂,而且在线程工作到一半释放一些例如打印机的资源,会使得进程前一段工作失效。
-
破坏循坏等待条件:给资源编序号,每次都只能先申请小号资源再申请大号。比如线程1需要A、B资源 ,线程2需要B、C资源,线程3需要C、A资源。我们排序ABC,那么线程三只能先申请A,得不到A就不能申请C.这样就不会出现在某一时刻,1拿了A,2拿了B,3拿了C,这样的死锁状态。
避免死锁
以银行家算法为例子,通过合适的资源调度来预防死锁。
用三个矩阵和一个数组的数据结构。
- 资源数组:整个数组用来存储可调用的资源数
- 最大需求资源矩阵
- 已分配资源矩阵
- 需求资源矩阵
最大需求资源矩阵=已分配资源矩阵+需求资源矩阵
情景
系统拥有空闲资源A:0 B:2 C:1
已分配资源矩阵:
线程/资源 | A | B | C |
---|---|---|---|
1 | 1 | 1 | 0 |
2 | 0 | 1 | 1 |
3 | 0 | 1 | 0 |
最大需求矩阵:
线程/资源 | A | B | C |
---|---|---|---|
1 | 1 | 1 | 0 |
2 | 1 | 2 | 1 |
3 | 1 | 1 | 0 |
可以计算出需求资源矩阵
线程/资源 | A | B | C |
---|---|---|---|
1 | 0 | 0 | 0 |
2 | 1 | 1 | 0 |
3 | 1 | 0 | 0 |
此时银行家算法是找到一个序列,使得线程按照这个序列进行,依次满足需求资源矩阵。比如序列 1 2 3
系统拥有空闲资源A:0 B:2 C:1 满足线程1需求的资源可以先进行线程1 ,1结束
此时系统拥有空闲资源A:1 B:3 C:1 此时进行线程2,线程2结束
此时系统拥有空闲资源A:1 B:4 C:2 此时进行线程3 结束
具体的实现可能得俩三百行,可以搜索。
死锁解除
当死锁已经发生时,接触死锁状态。
- 人工处理
- 抢占资源,从一个或多个进程中抢占资源分配给死锁进程
- 终止进程,终止一个或多个死锁进程直到打破死锁状态。