9人参与 • 2025-06-10 • Java
死锁(deadlock) 是指两个或多个线程因争夺资源而相互等待,导致所有线程都无法继续执行的一种状态。
只要这四个条件同时满足,就可能产生死锁。
下面是一个典型的死锁示例:
public class deadlockexample { private static final object locka = new object(); private static final object lockb = new object(); public static void main(string[] args) { thread t1 = new thread(() -> { synchronized (locka) { system.out.println("thread-1: locked a"); try { thread.sleep(100); } catch (interruptedexception e) {} synchronized (lockb) { system.out.println("thread-1: locked b"); } } }); thread t2 = new thread(() -> { synchronized (lockb) { system.out.println("thread-2: locked b"); try { thread.sleep(100); } catch (interruptedexception e) {} synchronized (locka) { system.out.println("thread-2: locked a"); } } }); t1.start(); t2.start(); } }
运行这段程序可能会导致 thread-1
等待 lockb
,thread-2
等待 locka
,从而产生死锁。
当应用卡住时,使用如下命令查看线程堆栈:
jps # 查找 java 进程 id jstack <pid>
你会看到类似:
found one java-level deadlock: "thread-1": waiting to lock monitor 0x000..., which is held by "thread-2" ...
这类工具可以图形化展示线程状态,识别死锁非常直观。
确保多个线程获取多个锁时 按相同顺序加锁。
public void safemethod() { synchronized (locka) { synchronized (lockb) { // 安全操作 } } }
使用 reentrantlock
的 trylock()
方法设置获取锁的超时时间。
import java.util.concurrent.locks.reentrantlock; import java.util.concurrent.timeunit; public class trylockexample { private final reentrantlock locka = new reentrantlock(); private final reentrantlock lockb = new reentrantlock(); public void run() { thread t1 = new thread(() -> { try { if (locka.trylock(1, timeunit.seconds)) { system.out.println("thread-1: locked a"); thread.sleep(100); if (lockb.trylock(1, timeunit.seconds)) { system.out.println("thread-1: locked b"); lockb.unlock(); } locka.unlock(); } } catch (interruptedexception e) { e.printstacktrace(); } }); thread t2 = new thread(() -> { try { if (lockb.trylock(1, timeunit.seconds)) { system.out.println("thread-2: locked b"); thread.sleep(100); if (locka.trylock(1, timeunit.seconds)) { system.out.println("thread-2: locked a"); locka.unlock(); } lockb.unlock(); } } catch (interruptedexception e) { e.printstacktrace(); } }); t1.start(); t2.start(); } public static void main(string[] args) { new trylockexample().run(); } }
避免使用低级的 synchronized
,使用高级并发工具如 executorservice
、semaphore
、lock
等更可控的工具。
一些大型系统中,可以通过定期扫描线程状态,自动检测死锁并重启部分线程或服务。例如通过自定义 threadmxbean
检测死锁。
最佳实践小结:
技术手段 | 说明 |
---|---|
加锁顺序统一 | 所有线程按相同顺序获取资源 |
trylock + timeout | 尝试加锁失败后避免长时间阻塞 |
lock 分解 | 将大锁拆分成小锁减少竞争 |
并发工具替代 synchronized | 使用 reentrantlock、semaphore 等 |
死锁检测工具 | 使用 jstack、visualvm 等工具 |
死锁是多线程编程中不可忽视的问题,但并不是无法避免。只要我们在设计时保持锁的有序性,并结合现代并发工具进行控制,绝大多数死锁问题都是可以预防的。
以上就是java死锁问题解决方案及示例详解的详细内容,更多关于java死锁问题解决的资料请关注代码网其它相关文章!
您想发表意见!!点此发布评论
版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。
发表评论