Bootstrap

如何检测和避免线程死锁?

  在日常开发中涉及到多线程开发时候就很容易会产生死锁

what:

什么是线程死锁?

线程死锁是指两个或两个以上的线程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞现象。当这些线程互相持有对方所需要的资源时,会互相等待对方释放资源,如果线程都不主动释放所占有的资源,将产生死锁。若无外力作用,它们都将无法推进下去,此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的线程称为死锁线程。

Why

线程死锁产生的四个必要条件包括:

  1. 互斥条件:一个资源,或者说一个锁只能被一个线程所占用,当一个线程首先获取到这个锁之后,在该线程释放这个锁之前,其它线程均是无法获取到这个锁的。
  2. 占有且等待:一个线程已经获取到一个锁,再获取另一个锁的过程中,即使获取不到也不会释放已经获得的锁。
  3. 不可剥夺条件:任何一个线程都无法强制获取别的线程已经占有的锁。
  4. 循环等待条件:线程A拿着线程B的锁,线程B拿着线程A的锁,形成循环等待的局面。

如何检测死锁?

  1.可以使用jdk自带的命令

  • 使用jmapjstack等命令查看 JVM 线程栈和堆内存的情况。如果有死锁,jstack 的输出中通常会有 Found one Java-level deadlock:的字样,后面会跟着死锁相关的线程信息。另外,实际项目中还可以搭配使用topdffree等命令查看操作系统的基本情况,出现死锁可能会导致CPU、内存等资源消耗过高。

   2.可以使用jdk自带的工具( JDK 的 bin目录下面)

  • 采用 VisualVM、JConsole 等工具进行排查。

 一般的话会采用第三方 Arthas

How

如何预防和避免线程死锁?

  1. 破坏请求与保持条件:一次性申请所有的资源。

  2. 破坏不剥夺条件:占用部分资源的线程进一步申请其他资源时,如果申请不到,可以主动释放它占有的资源。

  3. 破坏循环等待条件:靠按序申请资源来预防。按某一顺序申请资源,释放资源则反序释放。破坏循环等待条件。

;