本文目录导读:

我为您提供一个完整的Java死锁案例以及详细的排查方案。
死锁案例代码
import java.util.concurrent.TimeUnit;
public class DeadLockDemo {
// 定义两个资源锁
private static final Object lockA = new Object();
private static final Object lockB = new Object();
public static void main(String[] args) {
// 线程1:先获取lockA,再获取lockB
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
synchronized (lockA) {
System.out.println(Thread.currentThread().getName() + " 获取了lockA");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " 尝试获取lockB");
synchronized (lockB) {
System.out.println(Thread.currentThread().getName() + " 获取了lockB");
}
}
}
}, "Thread-1");
// 线程2:先获取lockB,再获取lockA
Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
synchronized (lockB) {
System.out.println(Thread.currentThread().getName() + " 获取了lockB");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " 尝试获取lockA");
synchronized (lockA) {
System.out.println(Thread.currentThread().getName() + " 获取了lockA");
}
}
}
}, "Thread-2");
thread1.start();
thread2.start();
}
}
更复杂的死锁案例(包含多个锁和嵌套调用)
import java.util.List;
import java.util.ArrayList;
public class ComplexDeadLock {
private final List<String> list1 = new ArrayList<>();
private final List<String> list2 = new ArrayList<>();
public void addToList1(String value) {
synchronized (list1) {
System.out.println(Thread.currentThread().getName() + " 锁定list1");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
list1.add(value);
// 嵌套获取list2
synchronized (list2) {
list2.add(value);
System.out.println(Thread.currentThread().getName() + " 同时锁定list1和list2");
}
}
}
public void addToList2(String value) {
synchronized (list2) {
System.out.println(Thread.currentThread().getName() + " 锁定list2");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
list2.add(value);
// 嵌套获取list1
synchronized (list1) {
list1.add(value);
System.out.println(Thread.currentThread().getName() + " 同时锁定list2和list1");
}
}
}
public static void main(String[] args) {
ComplexDeadLock deadLock = new ComplexDeadLock();
Thread t1 = new Thread(() -> {
for (int i = 0; i < 10; i++) {
deadLock.addToList1("value-" + i);
}
}, "Thread-A");
Thread t2 = new Thread(() -> {
for (int i = 0; i < 10; i++) {
deadLock.addToList2("value-" + i);
}
}, "Thread-B");
t1.start();
t2.start();
}
}
死锁排查方案
1 使用jstack命令排查
# 1. 首先找到Java进程ID jps # 2. 使用jstack查看线程堆栈 jstack <PID> > thread_dump.txt # 3. 或者直接输出到控制台 jstack <PID>
2 jstack输出示例
当发生死锁时,jstack会在末尾显示"Found one Java-level deadlock":
Found one Java-level deadlock:
=============================
"Thread-1":
waiting to lock monitor 0x00007f6d3800a800 (object 0x000000075a229640, java.lang.Object),
which is held by "Thread-2"
"Thread-2":
waiting to lock monitor 0x00007f6d3800a800 (object 0x000000075a229630, java.lang.Object),
which is held by "Thread-1"
Java stack information for the threads listed above:
===================================================
"Thread-1":
at DeadLockDemo$1.run(DeadLockDemo.java:32)
- waiting to lock <0x000000075a229640> (a java.lang.Object)
- locked <0x000000075a229630> (a java.lang.Object)
at java.lang.Thread.run(Thread.java:748)
"Thread-2":
at DeadLockDemo$2.run(DeadLockDemo.java:56)
- waiting to lock <0x000000075a229630> (a java.lang.Object)
- locked <0x000000075a229640> (a java.lang.Object)
at java.lang.Thread.run(Thread.java:748)
Found 1 deadlock.
3 使用jvisualvm图形化工具
# 启动JVisualVM jvisualvm
步骤:
- 在JVisualVM中双击需要查看的Java进程
- 选择"线程"标签页
- 如果有死锁,会看到红色提示
- 点击"线程转储"按钮可以获取详细的线程信息
4 使用jconsole监控工具
# 启动JConsole jconsole
步骤:
- 连接到需要监控的Java进程
- 切换到"线程"标签页
- 点击"检测死锁"按钮
5 自动化检测脚本
#!/bin/bash
# 死锁检测脚本 check_deadlock.sh
# 获取PID
PID=$1
if [ -z "$PID" ]; then
echo "Usage: ./check_deadlock.sh <PID>"
exit 1
fi
# 执行jstack并检查是否包含死锁关键字
JSTACK_OUTPUT=$(jstack $PID)
if echo "$JSTACK_OUTPUT" | grep -q "deadlock"; then
echo "警告: 检测到死锁!"
echo "========================================="
echo "$JSTACK_OUTPUT" | grep -A20 "deadlock"
else
echo "未检测到死锁"
fi
6 Spring Boot应用死锁排查
# application.yml 配置
management:
endpoints:
web:
exposure:
include: health,info,threaddump
访问:http://localhost:8080/actuator/threaddump
死锁排查步骤总结
- 检查日志: 查看应用日志中是否有超时或阻塞的提示
- 获取PID: 使用
jps或ps -ef | grep java找到Java进程ID - 执行线程转储: 使用
jstack <PID> -l获取详细线程信息 - 分析死锁: 找到线程堆栈中显示"Found one Java-level deadlock"的部分
- 分析代码: 根据堆栈信息定位到具体的代码行
- 确认资源分配: 查看哪些线程持有哪些锁,在等待哪些锁
可以采用以下命令快速排查:
# 1. jps查看所有Java进程 jps # 2. jstack转储线程并通过管道查找死锁 jstack <PID> | grep -A 10 "deadlock" # 3. 如果使用Linux还可以使用thread dump kill -3 <PID>
预防死锁的最佳实践
public class DeadLockPrevention {
// 方案1:统一锁的顺序
public void method1() {
synchronized (lockA) {
synchronized (lockB) {
// 业务逻辑
}
}
}
public void method2() {
synchronized (lockA) { // 和method1保持相同的锁顺序
synchronized (lockB) {
// 业务逻辑
}
}
}
// 方案2:使用tryLock方法
public void safeMethod() {
if (lockA.tryLock()) {
try {
if (lockB.tryLock()) {
try {
// 业务逻辑
} finally {
lockB.unlock();
}
}
} finally {
lockA.unlock();
}
}
}
// 方案3:使用并发工具类
private final ReentrantLock lock = new ReentrantLock();
public void concurrencySafeMethod() {
if (lock.tryLock(5, TimeUnit.SECONDS)) {
try {
// 业务逻辑
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
lock.unlock();
}
}
}
}
死锁分析工具总结
| 工具 | 命令 | 适用场景 |
|---|---|---|
| jstack | jstack <PID> |
命令行的快速排查 |
| JVisualVM | GUI工具 | 可视化分析,适合初学 |
| JConsole | GUI工具 | 实时监控和检测 |
| ThreadMXBean | 编程方式 | 应用内自动检测 |
| Java Flight Recorder | 性能分析 | 深入分析性能问题 |
使用编程方式检测死锁:
import java.lang.management.*;
public class DeadlockDetector {
public static void detectDeadlock() {
ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
long[] deadlockedThreads = threadMXBean.findDeadlockedThreads();
if (deadlockedThreads != null) {
ThreadInfo[] threadInfos = threadMXBean.getThreadInfo(deadlockedThreads);
System.out.println("检测到死锁! 涉及的线程:");
for (ThreadInfo ti : threadInfos) {
System.out.println(ti.getThreadName());
}
}
}
}
通过以上方法和工具,可以有效的排查和解决Java程序中的死锁问题。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播