1. 死锁
概念:一组并发进程因争夺系统资源而产生相互等待的现象。
原理:当一组进程中的每个进程都在等待某个事件的发生,而只有这组进程中的其他进程才能触发该事件,就称这组进程发生了死锁。
特征:发生死锁时,进程永远不能完成,系统资源被阻碍使用,以致于阻止了其他作业开始执行。
2. 必要条件
如果在一个系统中以下四个条件同时成立,那么就能引起死锁:
- 互斥(mutual exclusion):至少有一个资源必须处于非共享模式,即一次只有一个进程可使用。如果另一个进程申请该资源,那么申请进程应等到该资源释放为止。
- 占有且等待(hold and wait):一个进程应占有一个资源,并等待另一个资源,而该资源为其他进程所占有。
- 非抢占(no preemption):资源不能被抢占,即资源只能被进程在完成任务后自愿释放。
- 循环等待(circular wait):存在一组进程链,使得每个进程都占有下一个进程所需的至少一种资源。如有一组等待进程,等待的资源为占有, 等待的资源为占有,...... ,等待的资源为占有,等待的资源为占有。
当以上四个条件均满足时,必然会造成死锁,发生死锁的进程无法进行下去,它们所持有的资源也无法释放。这样就会导致CPU的吞吐量下降,死锁情况是会浪费系统资源和影响计算机性能的,那么解决死锁的问题就相当必要了。
2. 死锁预防
死锁预防(deadlock prevention)确保至少有一个必要条件不成立,通过限制如何申请资源的方法来预防死锁。发生死锁有4个必要条件,只要确保至少一个必要条件不成立,就能预防死锁发生。
- 互斥:互斥条件必须成立
- 破坏“占有且等待”条件
协议一 :每个进程在执行前申请并获得所有资源,可以通过申请资源的系统调用在所有其他系统调用之前进行。
优点:简单易实施且安全
缺点:许多资源可能已经分配,但长时间未使用,资源利用率比较低;一个进程可能需要多个常用资源,可能必须永久等待,容易发生饥饿。
协议二:该方法是对第一种方法的改进,它允许进程只获得运行初期需要的资源,便开始运行,运行过程中逐步释放掉分配到的已经使用完毕的资源,然后再去请求新的资源。这样的话,资源的利用率会得到提高,也会减少进程的饥饿问题。
- 破坏“不可抢占”条件
当一个已经持有了一些资源的进程在提出新的资源请求没有得到满足时,它必须释放已经保持的所有资源,待以后需要使用的时候再重新申请。这就意味着进程已占有的资源会被短暂地释放或者说是被抢占了。
这种方法实现起来比较复杂,且代价也比较大。释放已经保持的资源很有可能会导致进程之前的工作失效等;反复的申请和释放资源会导致进程的执行被无限延迟,这不仅会延长进程的运行周期,还会影响系统吞吐量。
- 破坏"循环等待"条件
对所有资源类型进行完全排序,要求每个进程按照递增顺序来申请资源。
这样虽然避免了循环等待,但是这种方法是比较低效的,资源的执行速度回变慢,并且可能在没有必要的情况下拒绝资源的访问。
在死锁预防算法中,通过限制如何申请资源来预防死锁。这种限制确保至少有一个死锁的必要条件不会发生。然而,通过这种方法预防死锁有副作用:设备使用率低和系统吞吐量低。
3. 死锁避免
死锁避免(deadlock avoidance)要求,操作系统事先得到有关进程申请资源和使用资源的额外信息。有了这些额外信息,系统可以确定:对于每个申请,进程是否应等待。为了确定当前申请是允许还是延迟,系统应该考虑:现有的可用资源、已分配给每个进程的资源及每个进程将来申请和释放的资源。
4. 死锁检测和恢复
如果系统不使用死锁预防或死锁避免算法,那么死锁情况可能发生。这种情况下,系统可以提供一个算法来检查系统状态以确定死锁是否发生,提供另一个算法来从死锁中恢复。