参考书籍:《Java高并发编程详解:多线程与架构设计》 汪文君 著
交叉死锁
线程 A 持有 R1 的锁等待获取 R2 的锁,线程 B 持有 R2 的锁等待获取 R1 的锁,这种情况最容易导致发生死锁的问题。
内存不足
当并发请求系统可用内存时,如果内存不足,则可能会出现死锁情况。
例如:有两个线程 T1 和 T2 ,执行某个任务,其中 T1 已经获取 10MB 内存,T2 获取了 20MB 内存,如果哦每个执行单元都需要 30MB 的内存,但是剩余可用内存刚好为 20MB ,很有可能两个线程等待彼此能够释放内存。
一问一答式的数据交互
这种请求方式就是,客户端请求一次,服务端响应一次,如果中间出现一次问题,导致服务器没有收到客户端的请求,那么程序就会一直阻塞。
数据库锁
无论是数据库的表锁,还是行锁。
例如:一个线程执行了 for update 语句退出了事务,其他线程访问该数据库的时候都将陷入死锁。
文件锁
一个线程获取了文件锁,但是意外退出了,其他读取该文件的线程也将会进入死锁状态,知道系统释放文件句柄资源。
死循环引起的死锁
程序可能由于处理不当,或者编码问题,进入死循环。这种情况一般称之为系统假死。
诊断方式
交叉锁引起的死锁
打开 jstack 工具或者 jconsole 工具, jstack -l PID 会直接发现死锁的信息。