概念
1. 死锁的定义
- 相互等待资源:死锁是指多个进程在执行过程中,由于互相等待对方所持有的资源,结果导致这些进程都处于阻塞状态,无法继续推进。这种情况使得系统中的所有相关进程都无法正常完成其任务。
- 饥饿:与死锁不同,饥饿是指一个进程由于长期无法获得所需要的资源而不能推进。一个典型的例子是短进程优先(SPF)调度算法中,如果有源源不断的新短进程到来,原本等待的长进程可能会一直得不到处理机,从而陷入“饥饿”状态。
原因
1. 资源竞争
- 资源争用:多个进程同时请求使用同一资源,而资源数量有限,导致进程之间因争取资源而发生竞争。
- 进程调度的非法顺序:如果进程在执行过程中,以错误的顺序请求资源,可能会导致死锁。例如,进程A请求资源X,然后请求资源Y;而进程B请求资源Y,然后请求资源X。当两个进程按照这种顺序同时请求时,可能导致死锁。
- 信号量的不当使用:错误地使用信号量(如semaphore)、互斥锁或条件变量等同步机制也可能导致死锁。例如,使用信号量时不恰当的顺序或条件,会导致进程互相等待对方的信号量。
产生的必要条件
1. 互斥条件
- 资源互斥使用:指某些资源在某一时刻只能被一个进程使用。只有对这种互斥使用的资源(如打印机、文件锁等)的争抢才会导致死锁。
2. 不剥夺条件
- 不可抢占资源:进程所获得的资源在未使用完毕之前,不能被其他进程强行夺走,只能由持有资源的进程主动释放。
3. 请求并保持条件
- 持有资源请求更多:进程已经保持了至少一个资源,但又提出了新的资源请求,而该资源已被其他进程占有,此时该请求进程被阻塞,但对自己已有的资源保持不放。
4. 循环等待条件
- 资源循环依赖:存在一种进程资源的循环等待链,链中的每一个进程已获得的资源被下一个进程所请求。在这种条件下,形成了一个循环依赖的链条,使得每一个进程都无法获取到所需的资源,从而形成死锁。
处理策略
1. 死锁预防
- 目的:通过破坏产生死锁的必要条件来预防死锁的发生。
- 具体策略:
- 破坏互斥条件:理论上不可行,因为对某些资源进行互斥使用是必须的。
- 破坏不剥夺条件:当某个进程请求新的资源无法满足时,它必须立即释放保持的所有资源,待以后需要时再重新申请。这种方法只适用于易于保存和恢复状态的资源,如CPU。
- 破坏请求并保持条件:采用静态资源分配方法,即进程在运行前一次性申请所有所需资源。这种方法资源利用率低,且可能导致进程饥饿。
- 破坏循环等待条件:采用顺序资源分配法,给系统中的资源编号,规定每个进程必须按编号递增的顺序请求资源。这种方法简单,但也可能导致资源利用率低下。
2. 死锁避免
- 目的:避免系统进入不安全状态,从而避免死锁。
- 系统安全状态:
- 安全序列:定义为系统按这种序列分配资源,则每个进程都能顺利完成。
- 安全状态的属性:如果系统处于安全状态,就一定不会发生死锁;而不安全状态未必一定发生死锁,但发生死锁时一定处于不安全状态。
- 银行家算法:
- 核心思想:在进程提出资源申请时,预判此次分配是否会导致系统进入不安全状态。若会进入不安全状态,就暂时不答应请求,让该进程先阻塞;若不会,则正式分配。
- 安全性算法:是银行家算法的一部分,主要用于判断满足当前要求后,系统是否处于安全状态。
- 具体步骤:
-
- 检查此次申请是否超过了之前声明的最大需求数。
-
- 检查此时系统剩余的可用资源是否还能满足这次请求。
-
- 试探性分配,更新数据结构。
-
- 使用安全性算法检查当前分配是否会导致系统进入不安全状态,若安全则正式分配;否则,恢复相应数据,让进程阻塞等待。
-
3. 死锁的检测与解除
- 目的:允许死锁发生,系统检测出死锁后,采取措施解除死锁。
- 死锁检测:
- 死锁定理:如果某个时刻系统的资源分配图是不可完全简化的,则系统发生了死锁。
- 资源分配图:一种描述系统中资源和进程之间请求关系的图。
- 死锁检测算法:通过化简资源分配图,确定哪些进程处于死锁状态。
- 死锁解除:
- 资源剥夺法:挂起某些死锁进程,并抢占它们的资源,将这些资源分配给其他进程,但应防止被挂起的进程长期得不到资源。
- 撤销进程法:强制撤销部分、甚至全部处在死锁状态的进程,释放这些进程持有的资源。
- 进程回退法:让一个或多个进程回退到足以避免死锁的地步,进程回退时自愿释放资源,而不是被剥夺。该方法需记录历史信息,设置还原点。