你真的理解什么是死锁吗?

一. 死锁的概念

两个或多个进程,因为资源的竞争或者彼此间的通讯而形成的阻塞现象,若是没有外力干预,它们将没法进行下去,这就发生了死锁。算法

更规范的定义:集合中的每个进程都在等待只能由本集合中的其余进程才能引起的事件(资源),那么该组进程是死锁的。安全

上面说到的竞争的资源能够是一切能称为资源的东西,好比锁,网络链接,通知事件,磁盘等网络

举个例子

比方说有两个线程,a 和 b工具

  • a 线程持有锁 a,等待锁 b
  • b 线程持有锁 b,等待锁 a

这样这两个线程就出现了死锁线程

二. 产生死锁的必要条件

  • 互斥条件:一个资源一次只能被一个进程访问;一旦分配给某个进程,其余进程就不能再访问(由于竞争资源的被占用是发生死锁的一个重要缘由)
  • 请求和保持条件:进程在等待其余线程占用的资源(请求),与此同时,进程会一直占用着本身已经得到的资源(保持)
  • 不可剥夺条件:进程对于已经申请到的资源在使用完成以前不能够被剥夺(也就是不会被其余进程抢走本身的资源)
  • 环路等待条件:发生死锁的进程组中,每个进程都会占有另外一个进程所须要的资源,这个占有关系能够造成一个等待环路(也就是竞争资源被相互占用,没法找到突破口,只能被死死堵着)

三. 如何预防和避免死锁

1. 以特定的顺序获取资源

以上面的例子来讲,A 线程先尝试获取 a 锁再尝试获取 b 锁;而 B 线程则相反。这样子的设计就极可能出现死锁。设计

若是一组线程都按照一样的顺序来尝试得到锁,那么就能够避免死锁的发生了。3d

2. 超时放弃

设置占有资源或者占有锁的最大时间,若是超过该时间仍未释放,那么就主动释放该资源cdn

3. 预先分配资源

在进程运行以前一次性的将其所需(申请)的资源分配给他,保证其能够正常的执行完毕,不须要在进程运行时再申请资源。blog

该方法的弊端体如今资源利用率低的方面,由于并非全部的资源在进程运行时都会被长时间占用,可是这样在运行前一次性分配的方式会形成全部资源在该进程的生命周期内都是不能够被释放的。生命周期

4. 银行家算法

银行家算法是一种直接避免死锁的方式,主要的思想就是动态检查进程对资源的申请,以检查是否会形成死锁。

咱们经过列出各个线程(进程)的当前占有的资源,最大所须要的资源以及当前剩余的可利用资源,能够计算可得知当前是否为安全状态(也就是必定不会发生死锁),简单来讲就是确保当前能够利用的资源是充足的

四. 检测死锁

若是咱们不去主动预防或者避免死锁,那么咱们能够经过及时检测当前是否出现死锁的方式来处理死锁问题,好比使用一些死锁检测算法

而何时去进行死锁检测又取决于死锁发生的频率以及通常状况下死锁涉及的进程数;这样,咱们既能够选择定时检测,也能够在发现资源利用率降低时进行检测,总之,你得知道发生死锁时,你的程序会有怎样的变化。

监控工具 JConsole

JDK 也自带了一个监控工具 JConsole,在JDK/bin目录下能够找到。

链接本地进程:

查询是否存在死锁:

五. 解除死锁

当发生了死锁以后,咱们确定要去解决掉它的。最直接的方法确定是重启,固然不少时候这样作不太可取。

  • 终止相关进程:检测出与死锁有关的进程,撤销或者挂起它,强制它释放资源
  • 剥夺资源:将部分被死锁进程占用的资源剥夺出来,解除死锁
  • 进程回退:将死锁进程回退到未出问题以前,不过实现难度较大。
相关文章
相关标签/搜索