【多线程学习】死锁排查

「这是我参与11月更文挑战的第27天,活动详情查看:2021最后一次更文挑战

死锁是什么?

在之前的笔记中有记录了死锁是什么,juejin.cn/post/702969… ,各自都拥有对方线程想要的资源,又在等待对方释放资源,互不相让

如果小向拿到了口红,然后想去拿散粉,同时小谢已经拿到了散粉,接着也想去拿口红,这时死锁就发生了。小向永远得不到散粉,小谢也永远得不到口红,她们永远也不会知道发生了这样的事情。为了得到彼此的拥有的东西(口红和散粉),她们将永远阻塞下去,这种情况就是一个死锁。

排查死锁

当线程卡在一个地方,不知道是不是死锁造成的问题,就可以使用以下方式去排查是否死锁了

自定义死锁demo

由于线程与线程之间的互相看对方都是乱序执行,因此加锁的顺序和释放顺序都是难以保证的,锁的互相嵌套在多线程下是一个很危险的操作,因此需要额外注意

利用之前笔记里面写的小谢和小向互相抢散粉和口红的死锁demo,来测试来排查死锁问题

image.png

互不相让,就会造成两个线程一直卡着

image.png

解决问题

  1. 使用查看当前进行的命令jps -l ,定位进程号,找出那个进程出现了问题。运行程序,使用idea工具的控制台输入命令查看进程号

image.png

  1. 定位到了进程,还需要知道这个进程是否有问题。使用命令jstack 进程号jcmd 进程号 Thread.print 查看进程的堆栈信息,这两个命令作用是相同的。依然是在idea工具的控制台输入命令加上刚刚查看到的进程号 jstack 15092

image.png

从打印出的信息可以看到,有两个线程,线程1拿到了c70结尾的锁在等待920结尾的锁,线程2拿到了920结尾的锁在等待c70结尾的锁

经过这样的排查,就可以看到程序的确造成了死锁,就可以去上锁的地方检查上锁的方式

特别注意

还有一种情况导致的死锁需要特别注意,由于某些中断操作没有释放掉锁,导致死锁。这种死锁也比较难排查

//加锁
//抛出异常
//释放锁
复制代码

所以对于资源释放语句一定要放在finally中