一句话总结
检测死锁:使用jstack分析线程转储或通过ThreadMXBean的findDeadlockedThreads方法。
预防死锁:1.按固定顺序获取锁,破坏循环等待;2.避免嵌套锁;3.使用tryLock设置超时机制;4.减少同步代码块范围。
详细解析
一、死锁的检测方法
- 线程转储分析
1.1 工具:jstack、VisualVM、JConsole。
1.2 步骤:
o 通过jstack <pid>生成线程转储文件。
o 搜索关键词deadlock,自动高亮死锁线程及锁依赖关系。
示例输出片段:
Found one Java-level deadlock:
"Thread-1": waiting to lock monitor 0x00007f8b1c004280 (object 0x000000076b39e4e8, a java.lang.Object),
which is held by "Thread-2"
"Thread-2": waiting to lock monitor 0x00007f8b1c003ae0 (object 0x000000076b39e4f0, a java.lang.Object),
which is held by "Thread-1"
2. 编程检测(ThreadMXBean)
o 代码示例:
import java.lang.management.ManagementFactory;
import java.lang.management.ThreadMXBean;
public class DeadLockDetector {
public static void main(String[] args) {
ThreadMXBean detector = ManagementFactory.getThreadMXBean();
long[] deadlockedThreads = detector.findDeadlockedThreads();
if (deadlockedThreads != null) {
System.out.println("检测到死锁线程:" + deadlockedThreads.length);
}
}
}
3.监控工具
o VisualVM:实时监控线程状态,自动标记死锁线程。
o APM工具:如 SkyWalking、Pinpoint,集成死锁检测告警功能。
三、死锁的预防与避免策略
1. 破坏互斥条件(不可行)
原因:锁的互斥性是线程安全的基础,无法破坏。
2. 破坏请求与保持条件
方案:线程一次性申请所有所需资源,未获取成功则释放已占资源
代码示例:
synchronized (lock1) {
if (tryLock(lock2)) { // 尝试获取lock2
try {
// 执行任务
} finally {
unlock(lock2);
}
}
}
3. 破坏不剥夺条件
方案:允许线程主动释放已持有的锁(如ReentrantLock.unlock())。
代码示例:
Lock lock = new ReentrantLock();
if (lock.tryLock()) {
try {
// 临界区
} finally {
lock.unlock(); // 主动释放
}
}
4.破坏循环等待条件
方案:按固定顺序获取锁(全局锁排序)。
代码示例:
// 定义锁的顺序
private static final Object[] locks = {lockA, lockB, lockC};
public void doWork() {
Arrays.sort(locks); // 按对象哈希值排序
synchronized (locks[0]) {
synchronized (locks[1]) {
synchronized (locks[2]) {
// 临界区
}
}
}
}
5.超时机制
方案:使用Lock.tryLock(timeout, unit)设置超时时间。
代码示例:
if (lock1.tryLock(1, TimeUnit.SECONDS)) {
try {
if (lock2.tryLock(1, TimeUnit.SECONDS)) {
try {
// 执行任务
} finally {
lock2.unlock();
}
}
} finally {
lock1.unlock();
}
}
6.资源分配策略
o 银行家算法:动态检测资源分配安全性,避免系统进入不安全状态(适用于实时系统)。
o 锁分级:将锁按优先级分级,高优先级锁优先分配。
7. 并发工具替代锁
o 无锁数据结构:如ConcurrentHashMap、AtomicInteger。
o 信号量(Semaphore):控制并发访问数量。
o
CountDownLatch/CyclicBarrier:协调线程执行顺序,避免嵌套锁。