程序死锁原因及其诊断

doMore 1,164 2021-06-20

参考书籍:《Java高并发编程详解:多线程与架构设计》 汪文君 著

交叉死锁

线程 A 持有 R1 的锁等待获取 R2 的锁,线程 B 持有 R2 的锁等待获取 R1 的锁,这种情况最容易导致发生死锁的问题。

内存不足

当并发请求系统可用内存时,如果内存不足,则可能会出现死锁情况。
例如:有两个线程 T1 和 T2 ,执行某个任务,其中 T1 已经获取 10MB 内存,T2 获取了 20MB 内存,如果哦每个执行单元都需要 30MB 的内存,但是剩余可用内存刚好为 20MB ,很有可能两个线程等待彼此能够释放内存。

一问一答式的数据交互

这种请求方式就是,客户端请求一次,服务端响应一次,如果中间出现一次问题,导致服务器没有收到客户端的请求,那么程序就会一直阻塞。

数据库锁

无论是数据库的表锁,还是行锁。
例如:一个线程执行了 for update 语句退出了事务,其他线程访问该数据库的时候都将陷入死锁。

文件锁

一个线程获取了文件锁,但是意外退出了,其他读取该文件的线程也将会进入死锁状态,知道系统释放文件句柄资源。

死循环引起的死锁

程序可能由于处理不当,或者编码问题,进入死循环。这种情况一般称之为系统假死。

诊断方式

交叉锁引起的死锁

打开 jstack 工具或者 jconsole 工具, jstack -l PID 会直接发现死锁的信息。