死锁可以正式地定义如下:
如果在一个进程集合中的每个进程都在等待只能由该集合中的另一个进程引发的事件,该组进程就被死锁。
产生死锁的条件
1.互斥条件
资源不能被共享,每个资源每次只允许一个进程使用或者空闲
2.占有和等待条件(请求与保持)
已占有某些资源的进程可以请求新的资源
3.不可抢占条件(不可剥夺)
已分配给一个进程的资源不能强制性地被抢占
4.环路等待条件(循环等待)
至少有2个或以上进程构成循环链
每个进程都在等待由循环链中下一个成员占有的资源
处理死锁有以下四种策略:
1.忽略该问题。
也许你忽视它,它也会忽视你
2.检测并恢复
允许死锁发生,然后检测它们,再采取行动。
3.通过仔细地资源分配来动态地避免死锁。
4.通过在结构上破坏死锁的四个必要条件之一来预防死锁。
解决死锁最简单的方法就是鸵鸟算法:把头埋到沙子里,假装根本没有问题发生。(视而不见)
理由:
死锁极少发生(page165)
预防死锁的代价太高
UNIX、Linux和Windows采用这方法
解决死锁问题通常要花很大代价,而且会给进程带来许多不便的限制。这是方便性与正确性的平衡
死锁检测和恢复
当使用该技术(死锁检测和恢复)时,系统并不试图阻止死锁的发生,相反,它允许死锁发生,当死锁发生时尝试去检测它,然后采取某些行动来进行恢复。
单资源类型的死锁检测
构造一个资源图,如果这张图包含了一个或多个的环路,那么就存在死锁。该环路中任何进程都被死锁。如果不存在环路,系统就不会死锁。
多资源类型的死锁检测
使用基于矩阵的算法来检测n个进程(从P1到Pn)中的死锁。
抢占法恢复
在某些情况下,临时将资源从其占有者拿走,并转交给另一个进程是可能的。很多情况下,需要人工干预,尤其是对大型主机上运行的批处理操作系统。
将资源从一个进程拿走,给另一个进程使用,并在不影响原进程的情况下返回,这种作法取决于该资源的特性。
回退法恢复
周期性地对进程设置检测点(checkpoint),即将进程状态写入文件以备稍后重启。
检测点中不仅包括内存映像,还包括资源状态,即哪些资源已经被指派给进程。
一旦检测到死锁,恢复时,进程回退到较早的检测点。
杀死进程来恢复
最粗鲁也是最简单的解决死锁的方法就是杀死一个或多个进程。
杀掉环路中的一个进程。
另外,也可以是将环路外的进程作为牺牲品,以释放资源。
最好杀死可以从头再运行而不会产生副作用的进程。
死锁预防
单资源的银行家算法
Dijkstra(1965)提出了一种能够避免死锁的调度算法,称为银行家算法(banker’s algorithm),该算法是死锁检测算法的扩展。
它是一个小镇的银行家为模型设计的,银行家向一群客户分别承诺了一定的贷款额度。
该算法所作的就是检查请求获准是否会导致不安全状态。如果会,请求即被拒绝;否则,批准其请求。
算法:
对每个资源请求检查满足它会否引起不安全状态,如果是不安全状态,则不满足此请求。
检测状态是否安全:此状态下是否有足够的资源满足一个距最大需求最近的客户。如果有,将此客户标记,(设客户运行结束)资源释放后,继续检查其他客户,直至所有客户都被标记则是安全状态,否则是不安全状态。
多资源的银行家算法
总结处理步骤:
Step1:
检查“仍需资源矩阵”中的每一行,判断是否存在一行,其所需资源总数小于向量A(剩余资源总数),失败则系统死锁。
Step2:
如存在此行,则将所有资源分配给该行对应向量,并将其状态标识为结束。
Step3:
重复1~2步,直至所有进程状态为结束。
如果所有进程状态均可标为结束,则状态安全,否则会发生死锁。