2.死锁产生原因
通过以上示例,我们可以得出结论,要产生死锁需要满足以下 4 个条件:
- 互斥条件:指运算单元(进程、线程或协程)对所分配到的资源具有排它性,也就是说在一段时间内某个锁资源只能被一个运算单元所占用。
- 请求和保持条件:指运算单元已经保持至少一个资源,但又提出了新的资源请求,而该资源已被其它运算单元占有,此时请求运算单元阻塞,但又对自己已获得的其它资源保持不放。
- 不可剥夺条件:指运算单元已获得的资源,在未使用完之前,不能被剥夺。
- 环路等待条件:指在发生死锁时,必然存在运算单元和资源的环形链,即运算单元正在等待另一个运算单元占用的资源,而对方又在等待自己占用的资源,从而造成环路等待的情况。
只有以上 4 个条件同时满足,才会造成死锁问题。
3.死锁排查工具
如果程序出现死锁问题,可通过以下 4 种方案中的任意一种进行分析和排查。
3.1 jstack
我们在使用 jstack 之前,先要通过 jps 得到运行程序的进程 ID,使用方法如下:
“jps -l”可以查询本机所有的 Java 程序,jps(Java Virtual Machine Process Status Tool)是 Java 提供的一个显示当前所有 Java 进程 pid 的命令,适合在 linux/unix/windows 平台上简单查看当前 Java 进程的一些简单情况,“-l”用于输出进程 pid 和运行程序完整路径名(包名和类名)。
有了进程 ID(PID)之后,我们就可以使用“jstack -l PID”来发现死锁问题了,如下图所示:
jstack 用于生成 Java 虚拟机当前时刻的线程快照,“-l”表示长列表(long),打印关于锁的附加信息。
PS:可以使用 jstack -help 查看更多命令使用说明。