news 2026/6/3 6:09:28

一文详解Java中死锁产生原因、常见场景及排查解决思路(附详细案例代码)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
一文详解Java中死锁产生原因、常见场景及排查解决思路(附详细案例代码)

01-死锁的概念

死锁是指两个或两个以上的线程在执行过程中,因抢夺资源而造成的一种互相等待的现象,若无外力干涉,则它们无法再继续推进下去

02-产生原因

  • 系统资源不足
  • 进程运行推进顺序不合适
  • 系统资源分配不当

03-常见死锁场景与示例

3.1嵌套锁顺序不一致

public class DeadLockDemo { static Object a = new Object(); static Object b = new Object(); public static void main(String[] args) { new Thread(() -> { synchronized (a){ System.out.println("t1线程持有a锁,试图获取b锁"); try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (b){ System.out.println("t1线程获取到b锁"); } } },"t1").start(); new Thread(() -> { synchronized (b){ System.out.println("t2线程持有a锁,试图获取a锁"); try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (a){ System.out.println("t2线程获取到a锁"); } } },"t2").start(); } }

分析:

  • t1线程执行:先获取a锁,再请求b锁
  • t2线程执行:先获取b锁,再请求a锁
  • 可能形成循环等待

3.2动态锁顺序死锁

public void transfer(Account from, Account to, int amount) { synchronized (from) { synchronized (to) { from.withdraw(amount); to.deposit(amount); } } }

分析:

如果两个线程同时调用transfer(),但参数顺序相反:

  • 线程A:transfer(account1, account2, 100)
  • 线程B:transfer(account2, account1, 200)

可能产生死锁

3.3资源死锁(如线程池任务相互等待)

ExecutorService executor = Executors.newFixedThreadPool(2); Future<?> future1 = executor.submit(() -> { Future<?> future2 = executor.submit(() -> System.out.println("Task2")); future2.get(); // 等待任务2完成 }); future1.get(); // 等待任务1完成

分析:

  • 线程池只有两个线程
  • 任务1提交任务2并等待任务2完成,任务2等待线程池空闲
  • 若任务2无法执行,任务1也无法完成,形成死锁

04-如何避免死锁

4.1 固定锁顺序

始终按全局一致顺序获取锁

public void transfer(Account a, Account b, int amount) { Object firstLock = a.id < b.id ? a : b; Object secondLock = a.id < b.id ? b : a; synchronized (firstLock) { synchronized (secondLock) { // 操作 } } }

4.2使用超时机制

tryLock()替代synchronized,设置超时时间

if (lock1.tryLock(100, TimeUnit.MILLISECONDS)) { try { if (lock2.tryLock(100, TimeUnit.MILLISECONDS)) { try { // 操作 } finally { lock2.unlock(); } } } finally { lock1.unlock(); } }

4.3 避免嵌套锁

尽量只持有一个锁,或 将多个锁封装为一个大锁

05-如何排查死锁

5.1 纯命令

  • jps -l—> 相当于 java ps -ef -l —>查看本地系统中所有正在运行的 Java 进程
  • jstack 进程编号—>查看进程堆栈信息

5.2 图形化

jconsole —>win + R 输入 jconsole,连接对应的Java进程,点击线程,点击检测死锁即可查看

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/3 13:20:56

5个关键R包搞定甲基化数据分析,生物信息新手也能快速上手

第一章&#xff1a;甲基化数据分析入门与R语言环境搭建 DNA甲基化是表观遗传学中的核心机制之一&#xff0c;通过在胞嘧啶上添加甲基基团影响基因表达而不改变DNA序列。随着高通量测序技术的发展&#xff0c;全基因组甲基化分析&#xff08;如WGBS、RRBS&#xff09;已成为研究…

作者头像 李华
网站建设 2026/6/2 15:07:17

UDP网络巩固知识基础题(5)

1. UDP协议在物联网(IoT)应用中的优势和实现要点? 答案: UDP在IoT环境中具有天然优势: 主要优势: 资源消耗低: 协议简单,内存和CPU占用少 功耗低: 无连接维护,减少无线电活动时间 实时性好: 适合传感器数据的及时上报 开销小: 适合传输小量数据 实现要点: 协议设…

作者头像 李华
网站建设 2026/6/3 21:03:58

Laravel 13多模态验证规则深度解析(前所未见的灵活验证方案)

第一章&#xff1a;Laravel 13多模态验证规则概述Laravel 13 引入了多模态验证规则系统&#xff0c;显著增强了表单请求和数据校验的灵活性与表达能力。该机制允许开发者在一个验证规则中组合多种条件模式&#xff0c;如基于请求方法、输入来源或上下文环境动态切换验证逻辑&am…

作者头像 李华
网站建设 2026/6/1 21:23:23

多模态缓存清理全解析,Laravel 13开发者必须掌握的3种高阶技巧

第一章&#xff1a;多模态缓存清理的核心概念与Laravel 13演进在现代Web应用开发中&#xff0c;缓存机制已成为提升系统性能的关键手段。随着Laravel 13的发布&#xff0c;框架对多模态缓存管理进行了深度优化&#xff0c;支持同时操作多种缓存后端&#xff08;如Redis、Memcac…

作者头像 李华
网站建设 2026/6/3 14:16:10

6G真的要来了?中国移动这次把“未来网络”摆到了台前

很多人对6G的印象&#xff0c;可能还停留在“5G都没用明白&#xff0c;6G是不是太早了”。但在12月中旬的中国信息通信大会上&#xff0c;中国移动把答案摆得很直白——不是概念图&#xff0c;也不是口号&#xff0c;而是一份白皮书&#xff0c;加上一台已经能跑起来的原型样机…

作者头像 李华
网站建设 2026/6/3 10:43:08

黄金成色怎么看?新手第一次买金,别只盯着“亮不亮”

第一次买黄金的人&#xff0c;十有八九都会被一个问题绊住&#xff1a;这金子&#xff0c;到底纯不纯&#xff1f;我身边就有朋友&#xff0c;拿着一条“看起来很黄”的项链反复端详&#xff0c;最后还是不放心地问柜员一句&#xff1a;“这是足金吗&#xff1f;”其实&#xf…

作者头像 李华