甲乙小朋友的房子

甲乙小朋友很笨,但甲乙小朋友不会放弃

0%

操作系统-死锁

死锁是进程死锁的简称,是由Dijkstra于1965年研究银行家算法时首先提出来的。它是计算机系统乃至并发程序设计中最难处理的问题之一。 抛开语言,用一个例子来聊一聊死锁问题,聊一聊它是怎么产生的?应该怎么防止?

经典哲学家就餐问题

场景:五个哲学家围在圆桌旁,每个人左手边有一只筷子。每个哲学家必须同时拿到两只筷子才能吃饭。(互斥使用)

问题模型:应用程序中并发线程执行中时,协调处理共享资源。

死锁:如果五个哲学家同时拿起左手边的筷子,就会死锁;

死锁的四个必要条件

  • 互斥条件:一个资源每次只能被一个进程使用(一只筷子只能被一个人用)
  • 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放 (哲学家不拿到第二支筷子,他就一直死等)
  •  不剥夺条件 :进程已获得的资源,在末使用完之前,不能强行剥夺(不能抢别人手里的筷子)
  • 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系 (五个哲学家相互等待)

一般来说,只要破坏掉死锁的其中一个必要条件,即可避免死锁。而互斥条件一般比较难以解决,所以我们从另外的三个条件入手。

可能的解决方案

  • 破坏死锁的请求与保持条件:

    • 仅当左右两边筷子都可用时,才允许他拿筷子。也就是说将拿两支筷子变成原子操作。比较简单的办法就是再加一个锁,所以同一个时间点只会有一个哲学家在拿筷子
    • 这种方法的好处是简单、易于实现且很安全,缺点却是资源被严重浪费,使进程延迟运行
  • 破坏死锁的不剥夺条件:

    • 当哲学家拿了一边的筷子以后,在去拿另一边的筷子的时候,发现无法拿,就放弃已经拿的筷子,以后在重新拿
    • 这种方法的缺点就是一个资源在使用一段时间后,它的被迫释放可能会造成前段工作的失效
  • 破坏循环等待条件:

    • 让哲学家按照某一种顺序去请求资源,使得在所形成的资源分配图中,不可能再出现环路。
      • 给哲学家编号,让奇数号的哲学家先拿右边的筷子,在拿左边的筷子,偶数号的哲学家先拿左边的筷子,在拿右边的筷子
      • 让最多4个哲学家能够有机会拿筷子,其中至少有一个哲学家能够拿起两边的筷子,不会产生死锁
    • 这种设计很考验技巧,很有可能使得程序的扩展性变得很差。