死锁

1、死锁的基本定义

死锁是指两个或者两个以上的进程在执行的过程中,由于竞争资源或有彼此通信造成的一种阻塞的现象,若无外力作用,他们都将无法执行下去。比如进程A持有进程B所需的资源,进程B持有进程C所需的资源,进程C持有进程A所持有的资源,那么A要执行需要等待C执行结束,进程B要执行需要等待进程A,进程C要执行要等待进程B执行结束,从而形成了一个闭环和互相等待的状态,那么显然,谁也不可能执行结束,此时就产生了死锁。参与死锁的进程称为死锁进程。

2、死锁产生的四个必要条件

1. 资源互斥:某段时间内资源只能分配并被某个进程占有;
2. 请求和保持:指进程已经持有一个或多个资源了,仍请求新的资源,而该资源被其他进程所占有,但又对自己所持有的其他资源不释放;
3. 不可剥夺:指进程已经获得的资源,在未使用之前,不可被剥夺;
4. 循环等待:即进程之间相互等待对方释放自己请求的资源,同时自己又占用其他进程请求的资源。

3、解决方法

3.1 死锁预防
破环死锁产生的条件,避免死锁的产生,如银行家算法,该算法由Dijkstra E.W 于1968年提出。另外还有有序资源分配法也可预防死锁的发生。
3.1.1 银行家算法
银行家算法顾名思义是来源于银行的借贷业务,一定数量的本金要应多个客户的借贷周转,为了防止银行家资金无法周转而倒闭,对每一笔贷款,必须考察其是否能限期归还。在操作系统中研究资源分配策略时也有类似问题,系统中有限的资源要供多个进程使用,必须保证得到的资源的进程能在有限的时间内归还资源,以供其他进程使用资源。如果资源分配不得到就会发生进程循环等待资源,则进程都无法继续执行下去的死锁现象。
把一个进程需要和已占有资源的情况记录在进程控制中,假定进程控制块PCB其中“状态”有就绪态、等待态和完成态。当进程在处于等待态时,表示系统不能满足该进程当前的资源申请。“资源需求总量”表示进程在整个执行过程中总共要申请的资源量。显然,每个进程的资源需求总量不能超过系统拥有的资源总数, 银行算法进行资源分配可以避免死锁。
3.1.2 有序资源分配法
这种算法资源按某种规则系统中的所有资源统一编号(例如打印机为1、磁带机为2、磁盘为3、等等),申请时必须以上升的次序。系统要求申请进程:
1. 对它所必须使用的而且属于同一类的所有资源,必须一次申请完;
2. 在申请不同类资源时,必须按各类设备的编号依次申请。例如:进程PA,使用资源的顺序是R1,R2; 进程PB,使用资源的顺序是R2,R1;若采用动态分配有可能形成环路条件,造成死锁。
采用有序资源分配法:R1的编号为1,R2的编号为2;PA:申请次序应是:R1,R2;PB:申请次序应是:R1,R2;这样就破坏了环路条件,避免了死锁的发生。
3.2 死锁避免
系统对进程发出的每一个系统能够满足的资源申请进行动态检查,并根据检查结果(是否会发生死锁)决定是否分配资源。
3.3 死锁检测和排除
及时的检测出死锁的发生,并精确的确定与死锁相关的进程和资源,然后解除死锁。常用的检测死锁的方法有:定时检测、效率低时检测、进程等待时检测等。
死锁排除的方法:
1. 撤销陷于死锁的全部进程;
2. 逐个撤销陷于死锁的进程,直至死锁不存在;
3. 从陷于死锁的进程中逐个强迫放弃所占用的资源,直至死锁消失;
4. 从其他占用资源的进程那强制夺取死锁进程所需的资源,解除死锁状态。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 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、付费专栏及课程。

余额充值