死锁

1.概念: 多个并发进程因争夺(互斥)资源而产生相互等待的现象。

2.产生死锁的本质原因:1)资源有限;2)进程推进顺序不合理。

3.产生死锁的必要条件

1)资源互斥。

2)资源占有并等待,指一个进程必须占有至少一个资源,同时又等待另一资源,而该资源已被其它进程占有。

3)不能抢占资源。

4)循环等待。存在等待进程集合{P0,P1,P2,···,Pn},其中的P0正在等待一个P1占用的资源;P1正在等待P2占用的资源,……,Pn正在等待已被P0占用的资源。(包含条件2)

4.问题建模:资源分配图

有向图;顶点(进程顶点,资源顶点);用圆型表示进程顶点,方形表示资源顶点,小黑点表示各类资源的实例;边(进程顶点到资源顶点,申请边;资源顶点到进程顶点,分配边);


总结:如果资源分配图中没有环,那系统就不会处于死锁。若有环,可能处于死锁状态(当每个资源有多个实例)。图中的环是死锁存在的必要条件而非充分条件

5.死锁处理的方法

1.鸵鸟策略

认为死锁在系统中是不会发生的,忽略死锁的产生。

2.死锁预防

通过设置某些限制资源申请的条件,去破坏产生死锁的四个必要条件中的一个或者几个,来预防发生死锁。

1)通常不能通过否定互斥条件来预防死锁。

2)破坏占有并等待:一是可以协议每个进程在执行前申请并获得所有资源;二是可以协议进程只有在没有资源的前提下才能申请资源。两种方式的缺点:资源利用率低,可能发生饥饿。

3)碰坏非抢占:规定一个进程占有资源并申请另一个不能立即分配的资源时,其占有的资源可被抢占。

4)破坏循环等待:对所有类型的资源进行排序,并规定每个进程按照递增的顺序的申请资源。

3.死锁避免

通过动态的资源分配状态以及合理的资源分配算法以确保循环等待的条件不会成立,从而避免死锁。

安全状态:针对当前状态,即下面四个条件,如果能够按照某个次序调度资源使得每个进程都能够运行完毕,则称此状态是安全状态。

四个条件:现有各类资源的数目,已分配的资源数目,可用的各类资源数,每个进程对各类资源的最大需求数。

银行家算法(下面第二种检测算法的变种):需要事先知道每个进程在运行前所需资源的最大值。

针对每一个请求进行检查,观察如果满足这一请求是否能够达到安全状态,若能达到,则满足此请求;否则就不满足。

4.死锁检测

1)每种资源有单个实例

检测方法:采用资源等待图,若其中有环存在,则系统存在死锁

等待图:资源分配图的变种。


2)每种资源有多个实例

采用一种基于矩阵的算法,有四个条件,一是现有总资源向量E,可用资源向量A,当前资源分配矩阵C,进程未来的资源请求矩阵R。

此算法分三步:

一,寻找一个进程,满足R《A。

二,若存在这样的进程,先标记其,认为其可运行完毕。然后A=A+C(此进程所分配的资源)。

三,上述两步要不断进行,直到若不存在这样的进程,或者所用进程都被标记,则算法结束。

算法结束,若存在没有被标记的进程,则系统中存在死锁。

总结:死锁检测的时机:一是每当有资源申请时就检测。二是可以每隔一段时间检测一次。三是当CPU的利用率降到某一阈值时去检测。

5.死锁恢复(回收资源)

一是终止进程,包括终止环中的进程(即死锁进程)和终止环外进程(牺牲品)(目的是释放资源)。

二是抢占资源,被抢占资源的进程要利用回滚恢复,一般回滚到一个安全状态。通常是完全回滚,即终止进程并重启进程。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
死锁是指两个或多个进程在互斥地请求资源的时候,由于资源被占用而无法继续执行,导致所有进程都被阻塞的情况。在Spring Boot中,死锁可能发生在多线程并发访问共享资源时,例如数据库连接池、缓存、锁等。 在给出解决方案之前,我们需要先排查死锁问题。一种常用的排查死锁问题的方法是使用jstack命令输出线程的堆栈信息。通过查看堆栈信息,我们可以定位到可能引起死锁的代码行,并进行解决修复。 下面是一个示例代码,模拟了一个可能导致死锁的场景: ```java package com.xz.springboottest.day1; public class DeadLock { private static final String ACTION_ONE = "拿起碗"; private static final String ACTION_TWO = "拿起筷子"; public static void main(String[] args) { // 哲学家小明 new Thread(() -> { synchronized (ACTION_ONE) { try { Thread.sleep(1000); synchronized (ACTION_TWO) { System.out.println("小明开始吃饭了。。。。。。"); } } catch (InterruptedException e) { e.printStackTrace(); } } }).start(); // 哲学家小张 new Thread(() -> { synchronized (ACTION_TWO) { try { Thread.sleep(1000); synchronized (ACTION_ONE) { System.out.println("小张开始吃饭了。。。。。。"); } } catch (InterruptedException e) { e.printStackTrace(); } } }).start(); } } ``` 以上代码模拟了哲学家就餐的场景,当只剩下一只碗和一双筷子时,可能出现死锁的问题。 对于解决死锁的方法,可以考虑以下几种方案: 1. 避免循等待:为了避免死锁,可以规定所有线程在请求资源时按照固定的顺序获取,从而避免循等待。 2. 加锁顺序:在多个线程同时请求多个资源的情况下,为了避免死锁,可以约定线程必须按照相同的顺序请求资源。 3. 设置超时时间:在获取锁的时候设置超时时间,如果超过一定时间还未获取到锁,可以放弃或者重试。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值