死锁的产生及处理策略条件

死锁

什么是死锁?

我们先从互斥量造成的死锁说起。

当一个线程去申请一个已经被持有,但是还没有释放的互斥量时,线程将会被阻塞,直到该互斥量被释放。如果该互斥量不被释放,该线程将会被一直阻塞。

因次,基于以上的原因,我们可以认为当一个线程去申请一个永远不会被释放的互斥量时,该线程将会被永远阻塞,这种情景我们称之为死锁。更宽泛的说,死锁就是,一个线程阻塞的等待一个永远不会为真的条件

以下为两个常见的互斥量中死锁场景

(1)当一个线程重复的拿取同一个互斥量

当一个线程申请到该互斥量后,在持有该互斥量的同时,再次申请该互斥量。而此时,因为该互斥量已经被它自身持有,再次申请时,该线程将会被阻塞。但是改互斥量必须被被它自身释放后,才能继续被申请。但此时,线程被阻塞,将永远无法释放锁,并再次申请。所以该线程将会被永远阻塞。这种场景会出现在,在一个函数的内部存在对锁的申请,当一个线程调用该函数申请到锁后,在锁的内部再次调用该函数,就会出现该线程对一个互斥量同时申请两次。

在这里插入图片描述
(2)当两个线程,对两个互斥量以相反的顺序进行相互持有

假如有两个线程 A B ,有两个 互斥量 1 和 2,线程A先申请2锁 ,线程B先申请1锁,当线程A申请完2 后,在持有2的同时去申请1,当线程B申请完1后,在持有1的同时去申请2.但是此时,双方都去申请对方的锁,但是锁被对方持有,所以两个线程只能阻塞等待,在陷入阻塞后,双方持有的锁都将无法释放,所以两个线程将会永远的阻塞。从而造成死锁。

在这里插入图片描述

以上两种场景是在互斥量的条件下,常见的死锁场景,但是这两种造成死锁的场景,并不局限于互斥量,只要满足产生死锁的条件,就会出现死锁。

前人总结了产生了死锁的四个必要条件:

  • 互斥条件。

与锁一样,要么能被申请,要么就只能等待。在任意时刻,某份资源只能被一个进程或线程使用。

  • 占有和等待条件。

是指某个线程或进程,在占有某份资源后还可以申请其他的资源。

  • 不可抢占条件。

当某份资源被某一进程或线程占有时,不能被其他线程或进程强制性的抢占,只能被占有它的线程主动的释放。

  • 环路等待条件。

死锁发生时,系统中一定有两个或两个以上的进程组成的一条环路,该环路中的每一个线程或进程都在等待下一个进程所占用的资源。

以上的四个条件必须同时满足,才会可能造成死锁。只要有一个条件不满足,就不会造成死锁。

死锁的产生并不仅会只有互斥量时会发生,只要满足以上四个条件即可。在系统中,有许多只能被互斥性访问的独占资源,如请求独占性的io设备,打印机等,在对其进行操作时,也有可能造成死锁。

处理死锁的四种策略

(1)忽略该问题。

把死锁忽略,不注意死锁。有的死锁产生的时间并不确定。而且死锁发生的频度,造成问题的严重性不同。假如对于一个死锁每隔几个月或者每个几年出现一次,而且每次造成的问题并不严重,那么此时,工程师可能并不会以损失可用性或性能损失的代价去防止死锁。此种情况下就属于忽略死锁的问题。

(2)检测死锁并恢复。

当出现死锁时,通过检测死锁的技术,检测到出现的死锁,对于找到的死锁进行恢复。

(3)仔细对资源分配,动态的避免死锁。
(4)通过破坏引起死锁的四个必要条件之一,以此来避免死锁。

猜你喜欢

转载自blog.csdn.net/M_jianjianjiao/article/details/84729628