多线程之死锁

介绍

  死锁是指两个或两个以上进程(在运行的过程中因争夺资源而造成的一种僵局),若无外力作用,这些线程,进程都将无法向前推进。

  • 参与死锁的进程(线程)至少为2个
  • 参与死锁的进程(线程)均等待资源
  • 参与死锁的进程(线程)至少有2个已经占有资源
  • 死锁进程是系统中当前进程集合的一个子集
  • 死锁会浪费大量系统资源,甚至导致系统崩溃

资源

  所有的死锁都是对资源的争夺造成的,资源是一切的罪魁祸首。

永久资源与临时资源

永久资源

  永久资源可以被多次使用,如所有硬件。

  • 只能分配给一个进程使用,不允许多个进程共享
  • 进程使用时,需按照请求资源、使用资源、释放资源的顺序
  • 这种资源的数量是固定的,运行期间,不能创建,也不能销毁

临时资源

  是在运行期间动态创建和销毁的资源。

  • 数量在运行期间是不断变化的,有可能为0
  • 在运行过程中,可以不断的创建这种资源,将它们放入缓冲区,增加资源数量
  • 也可以在运行过程中,请求几个临时资源,用于运行中的消耗

  一般由生产者进程产生,消费者进程消耗,如何用于通信的消息。

可抢占资源和不可抢占资源

可抢占资源

  可抢占资源指某进程在获得这类资源后,该类资源可以被其他进程或系统抢占,也就是大家共享,这类资源不会引起死锁。比如CPU和内存。

不可抢占资源

  一旦系统将某资源分配给该进程后,就不能将其强行收回,只能在进程使用完后自己释放。比如打印机。


死锁原因

  • 竞争不可抢占资源引起死锁

    通常系统中的不可抢占资源,其数量不足以满足同时运行,使得在运行过程中,会因资源抢占而进入僵局,造成死锁。

  • 竞争可消耗资源引起死锁
  • 进程推进顺序不当引起死锁

    运行过程中,请求和释放资源的顺序不科学,也会造成死锁,我等你,你等我的情况。
    信号量使用不当也会死锁,进程间彼此相互等待对方发来的消息,结果也会使得这 些进程间无法继续向前推进。


死锁条件

互斥条件

  运行的进程对它所分配的资源进行排他性控制,在一段时间内某资源仅为一个进程所占用。此时若有其他进程线程来请求资源,则请求的进程线程只能等待。

不可剥夺条件

  所获得的资源,已经占用的资源,不能被其他进程强行夺走,只能由自己主动释放。

请求与保持

  进程已经保持占用了至少一个资源,但又提出了新的资源请求,而该资源已经被其他进程占有,此时进程请求被阻塞,但对自己已获得资源保持占用。

循环等待

  存在进程资源间的循环等待链。


处理死锁

  • 预防死锁:通过设置某些限制条件,去破坏产生死锁的四个条件的一个或几个。
  • 避免死锁:在资源的动态分配过程中,用某种方法防止系统进入不安全状态,从而避免死锁发生。
  • 检测死锁:允许系统在运行过程中发生死锁,但可设置检测机构及时检测死锁的发生,并采取适当措施加以清除。
  • 解除死锁:当检测出死锁后,便采取适当措施将进程从死锁状态中解脱出来。

预防死锁

破坏互斥条件

  就是在系统里取消互斥。若资源不被一个进程独占使用,那么死锁是肯定不会发生的。
  实际情况中,互斥条件一般不能也无法被破环,否则会造成结果不可再现。

破环不可抢占条件

  就是允许对资源实行抢夺。

  • 如果占有某些资源的一个进程进行进一步资源请求被拒绝,则该进程必须释放它最初占有的资源,如果有必要,可再次请求这些资源和另外的资源。
  • 如果一个进程请求当前被另一个进程占有的一个资源,则操作系统可以抢占另一个进程,要求它释放资源。只有在任意两个进程的优先级都不相同的条件下,方法二才能预防死锁。

破环请求与保持条件

  就是在系统中不允许进程在已获得某种资源的情况下,申请其他资源。即要想出一个办法,阻止进程在持有资源的同时申请其他资源。

  • 创建进程时,要求它申请所需的全部资源,系统或满足其所有要求,或什么也不给它。这是所谓的 “ 一次性分配”方案。
  • 要求每个进程提出新的资源申请前,释放它所占有的资源。这样,一个进程在需要资源S时,须先把它先前占有的资源R释放掉,然后才能提出对S的申请,即使它可能很快又要用到资源R。

破环循环等待条件

  破坏“循环等待”条件的一种方法,是将系统中的所有资源统一编号,进程可在任何时刻提出资源申请,但所有申请必须按照资源的编号顺序(升序)提出。这样做就能保证系统不出现死锁。

避免死锁

  合理规划资源,在系统资源,进程调度等方面,设计让死锁条件无法满足,避免进程永久占据系统资源或在等待条件下占用资源,从而防止死锁。
  预防死锁和避免死锁的区别:预防死锁是设法至少破坏产生死锁的四个必要条件之一,严格的防止死锁的出现,而避免死锁则不那么严格的限制产生死锁的必要条件的存在。因为即使死锁的必要条件存在,也不一定发生死锁。避免死锁是在系统运行过程中注意避免死锁的最终发生。

避免死锁的方法

  • 有序资源分配法
  • 银行家算法

避免死锁的技术

  • 加锁顺序
  • 加锁时限
  • 死锁检测

检测死锁

  死锁检测与恢复是指系统设有专门的机构,当死锁发生时,该机构能够检测到死锁发生的位置和原因,并能通过外力破坏死锁发生的必要条件,从而使得并发进程从死锁状态中恢复出来。

解除死锁

  死锁解除的方法有:

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

参考文献 & 鸣谢