排查死锁方法样例(Java)
Java死锁是指两个或多个线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力干涉那它们都将无法推进下去。死锁是多线程编程中常见的问题,也是比较难以调试和解决的问题。
死锁产生的四个必要条件:
-
互斥条件:一个资源每次只能被一个进程使用。
-
请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
-
不剥夺条件:进程已获得的资源,在未使用完之前,不能强行剥夺。
-
循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。
解决死锁的方法:
-
预防死锁:破坏死锁的四个必要条件之一,如破坏请求与保持条件,一次性申请所有资源。
-
避免死锁:在资源分配前,根据资源的可用情况,预判是否会发生死锁,如果会发生,则不分配资源。
-
检测死锁:通过算法检测死锁的发生,一旦发现死锁,采取相应的措施,如撤销进程,回收资源等。
-
解除死锁:当检测到死锁时,采取一定的措施进行解除,如撤销进程,回收资源等。
样例:
package com.rojer.test.threadtest;
import java.util.concurrent.TimeUnit;
public class LockDemo {
public static void main(String[] args) {
LockDemo lockDemo1 = new LockDemo();
LockDemo lockDemo2 = new LockDemo();
new Thread(() -> {
synchronized (lockDemo1) {
System.out.println(Thread.currentThread().getName() + " 获取了对象1的锁");
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
synchronized (lockDemo2) {
System.out.println(Thread.currentThread().getName() + " 获取了对象2的锁");
}
}
}, "线程1").start();
new Thread(() -> {
synchronized (lockDemo2) {
System.out.println(Thread.currentThread().getName() + " 获取了对象2的锁");
synchronized (lockDemo1) {
System.out.println(Thread.currentThread().getName() + " 获取了对象1的锁");
}
}
}, "线程2").start();
}
}
运行后就能看到程序处于无法终止的状态。
方法1:
通过 jps -l 定位到线程类对应的编号
通过jstack命令观察堆栈信息
如图:
方法2:
使用jconsole(本地就填本地连接,远端填远端ip端口)
点击检测死锁