在日常开发中涉及到多线程开发时候就很容易会产生死锁
what:
什么是线程死锁?
线程死锁是指两个或两个以上的线程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞现象。当这些线程互相持有对方所需要的资源时,会互相等待对方释放资源,如果线程都不主动释放所占有的资源,将产生死锁。若无外力作用,它们都将无法推进下去,此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的线程称为死锁线程。
Why
线程死锁产生的四个必要条件包括:
- 互斥条件:一个资源,或者说一个锁只能被一个线程所占用,当一个线程首先获取到这个锁之后,在该线程释放这个锁之前,其它线程均是无法获取到这个锁的。
- 占有且等待:一个线程已经获取到一个锁,再获取另一个锁的过程中,即使获取不到也不会释放已经获得的锁。
- 不可剥夺条件:任何一个线程都无法强制获取别的线程已经占有的锁。
- 循环等待条件:线程A拿着线程B的锁,线程B拿着线程A的锁,形成循环等待的局面。
如何检测死锁?
1.可以使用jdk自带的命令
-
使用
jmap
、jstack
等命令查看 JVM 线程栈和堆内存的情况。如果有死锁,jstack
的输出中通常会有Found one Java-level deadlock:
的字样,后面会跟着死锁相关的线程信息。另外,实际项目中还可以搭配使用top
、df
、free
等命令查看操作系统的基本情况,出现死锁可能会导致CPU、内存等资源消耗过高。
2.可以使用jdk自带的工具( JDK 的 bin目录下面)
-
采用 VisualVM、JConsole 等工具进行排查。
一般的话会采用第三方 Arthas
How
如何预防和避免线程死锁?
-
破坏请求与保持条件:一次性申请所有的资源。
-
破坏不剥夺条件:占用部分资源的线程进一步申请其他资源时,如果申请不到,可以主动释放它占有的资源。
-
破坏循环等待条件:靠按序申请资源来预防。按某一顺序申请资源,释放资源则反序释放。破坏循环等待条件。