性能问题之线程死锁

定义

线程死锁就是有两个线程,一个线程锁住了资源A,又想去锁住资源B,另外一个线程锁定了资源B,又想去锁定资源A,两个线程都想去得到对方的资源而又不愿意释放自己的资源,从而造成了一种互相等待、无法执行的情况。

 

现象

出现死锁后,TPS降为0,性能测试工具无法得到服务器的响应,

服务器硬件资源空闲

通过jvisualvm去查看线程情况,至少两个线程一直处于红色的阻塞状态

 

案例分析

1、某接口压测5分钟结果如下:

从上面三幅图片可以看出:

  (1)从测试工具jmeter可以看出,5分钟还未到,测试过程还在继续,但是其实从第15秒之后就没有请求。

  (2)查看机器资源,从图中可以得出,机器的CPU资源占用率很低,远未达到瓶颈。

根据线程死锁的现场,猜测此时是发生了线程死锁。

 

 2、验证猜想

方法一:通过jstack命令查看线程情况。对线程代码进行分析,获取到哪行代码导致的死锁。

jstack pid > filename.log

将dump下来的文件下载到本地,通过deadlock进行查找:

把图中的Deadlock内容复制出来:

http-nio-8080-exec-9- waiting to lock <0x00000000e6a31c68>
    - locked <0x00000000e6a31c88>
http-nio-8080-exec-1- waiting to lock <0x00000000e6a31c88>
    - locked <0x00000000e6a31c68>
由上可知:线程http-nio-8080-exec-9和http-nio-8080-exec-1死锁。
分别在日志中查找http-nio-8080-exec-9和http-nio-8080-exec-1,可以看到都是BLOCKED状态;同时可以将问题代码位置反馈给开发。

 

方法二:通过jvisualvm查看

首先是调整远程监控的参数:
JAVA_OPTS="-Xms650m -Xmx650m -XX:+HeapDumpOnOutOfMemoryError -Dcom.sun.management.jmxremote.port=10086 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -Djava.rmi.server.hostname=192.168.0.110"

其中-Djava.rmi.server.hostname:远程连接地址,即程序所在机器地址

jvisualvm连接后如下:

上图中明显警告检测到了死锁,从图中线条的颜色也能看出来死锁的线程。

此时点击右上角“线程dump”,dump成功后如下,分析方法与jstack结果分许一致。

 

posted @ 2022-04-14 19:01  阳光倾林  阅读(379)  评论(0编辑  收藏  举报