死锁的必要条件和解决方法


死锁与饥饿的区别

  • 死锁:死锁是指多个进程一直得不到某个资源,并且不会释放自己已经拥有的资源,一直等待下去。
  • 饥饿:饥饿是指一个进程长时间得不到自己需要的某个资源
    死锁一定属于饥饿,但是饥饿不一定是死锁,可能某个时间只会又会得到所需的资源,则饥饿解除。饥饿可以只有一个进程参与,比如某个进程申请一个没有的资源。死锁至少有两个进程。

死锁的四个必要条件

  • 资源互斥:即某个资源同一时间只能给一个进程使用,资源不可共享。
  • 已拥有的资源不可被剥夺:一个进程已经拥有的资源不可被其他进程剥夺
  • 已拥有的资源不会主动放弃:一个进程已经拥有的资源不会主动放弃
  • 等待:某个资源没有申请到的时候一直等待

预防死锁

破坏死锁的四个必要条件,就能防止死锁,资源互斥不可能破坏,资源共享容易发生问题,一般同一时间只能被一个进程使用,因此可以考虑破坏其他三个条件

  • 破坏《已拥有的资源不可被剥夺》:当某个进程申请不到某个资源时,操作系统强制或者进程自己主动释放已经拥有的资源,或者操作系统强制让用用这个资源的进程释放资源
  • 破坏《已拥有的资源不会主动放弃》:在申请资源的时候,主动释放掉已经拥有的资源,即使马上就要用到
  • 破坏《等待》:在进程开始运行前先申请好所有的资源,要么都申请到,要么一个都不要。这样就不会有等待的需求了。

避免死锁

预防死锁和避免死锁的区别:

预防死锁是设法至少破坏产生死锁的四个必要条件之一,严格的防止死锁的出现,在进程运行之前就能确保肯定不会发生死锁

而避免死锁则不那么严格的限制产生死锁的必要条件的存在,因为即使死锁的必要条件存在,也不一定发生死锁。避免死锁是在进程运行过程中注意避免死锁的最终发生。

  • 资源统一编号:把所有资源统一编号,进程在运行过程中随时可以申请资源,但是必须按照编号递增顺序,如果某个地方需要申请编号为n的资源,则在这之前必须先申请好编号1到n的资源。这样进程在申请某个资源而不得的时候就不会拥有这个资源前面的资源,就不会发生死锁。
  • 银行家算法

检测死锁

死锁的预防和避免都是在进程申请资源时进行控制,但在申请资源时控制也会有一些成本,有的算法实现难度大,如果在进程申请资源时不控制,即允许死锁的发生,则必须提供死锁的检测和接触方法。

  • 资源分配图:用圆圈代表一个进程,用框代表一类资源。由于一种类型的资源可能有多个,用框中的一个点代表一类资源中的一个资源。从进程到资源的有向边叫请求边,表示该进程申请一个单位的该类资源;从资源到进程的边叫分配边,表示该类资源已经有一个资源被分配给了该进程。


上图所示的资源分配图中,进程P1已经分得了两个R1资源,并又请求一个R2 资源;进程P2分得了一个R1和一个R2资源,并又请求一个R1资源。

检测上述系统释放死锁的步骤如下:

1.检查所有节点,如果某个进程能够运行完(即它所申请的资源足够多,可以满足它的运行),则假设这个进程已经运行完,去掉它锁拥有的所有资源.

2.循环遍历所有进程节点,按步骤1操作,最终如果上图中所有的边都消失了,则称该系统是可完全简化的。

可简化的系统就没有发生死锁,不可简化的系统则发生了死锁。

解除死锁

解除死锁就是破坏上图的引用关系,使得上图变成可简化的系统。主要有以下三种方法:

  • 资源剥夺:挂起某些死锁进程,并抢占它的资源,将这些资源分配给其他的死锁进程。但应防止被挂起的进程长时间得不到资源,而处于资源匮乏的状态。
  • 强制杀死进程:强制撤销部分、甚至全部死锁进程并剥夺这些进程的资源。撤销的原则可以按进程优先级和撤销进程代价的高低进行。
  • 进程回退:让一(多)个进程回退到足以回避死锁的地步,进程回退时自愿释放资源而不是被剥夺。要求系统保持进程的历史信息,设置还原点。

参考

【1】死锁,死锁的四个必要条件以及处理策略

【2】死锁的检测和解除


文章作者: Alex
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Alex !
  目录