当前位置: 首页 > news >正文

Java死锁的例子

创建两个线程,每个线程先锁定一个对象,再尝试获取对方持有的对象。当线程1锁定A后请求B,线程2锁定B后请求A时,形成循环等待导致死锁。核心代码使用synchronized嵌套锁,通过Thread.sleep(100)确保锁竞争顺序,运行后线程会相互阻塞无法继续执行。

public class DeadlockDemo {// 定义两个不可变的锁对象private static final Object lock1 = new Object();private static final Object lock2 = new Object();
​public static void main(String[] args) {// 线程1:先获取lock1,再尝试获取lock2Thread thread1 = new Thread(() -> {synchronized (lock1) {System.out.println("Thread 1: 持有 lock1");try {// 休眠确保线程2能获取lock2Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("Thread 1: 等待 lock2...");synchronized (lock2) {System.out.println("Thread 1: 同时持有 lock1 和 lock2");}}});
​// 线程2:先获取lock2,再尝试获取lock1Thread thread2 = new Thread(() -> {synchronized (lock2) {System.out.println("Thread 2: 持有 lock2");System.out.println("Thread 2: 等待 lock1...");synchronized (lock1) {System.out.println("Thread 2: 同时持有 lock1 和 lock2");}}});
​thread1.start();thread2.start();}
}

死锁产生过程分析:

  1. 线程启动顺序

    • thread1 先获取 lock1 并休眠 100ms(此时未释放 lock1

    • thread2趁休眠期获取lock2

  2. 阻塞等待

    • thread1 醒来后尝试获取 lock2(但 thread2 正持有 lock2

    • thread2同时尝试获取lock1(但thread1正持有lock1)

  3. 循环等待 两线程互相持有对方需要的锁,且都不释放,形成永久阻塞。

验证死锁方法(命令行操作):

jps                  # 查看Java进程ID(假设进程ID为12345)
jstack 12345         # 分析线程堆栈

输出结果会显示:

Found one Java-level deadlock:
"Thread-1":waiting to lock monitor 0x00007fdf0e80ed68 (held by Thread-0)
"Thread-0":waiting to lock monitor 0x00007fdf0e8100a8 (held by Thread-1)

关键注意点:

  1. 必要条件 死锁需同时满足:互斥使用、不可抢占、请求与保持、循环等待。

  2. 确定性设计 示例中 Thread.sleep(100) 是为​​确保死锁必然发生​​(模拟实际业务中的操作延迟)。若无此延迟,可能因线程执行速度过快而规避死锁。

解决思路(代码改进方向):

  1. 统一锁顺序 所有线程按固定顺序获取锁(如都先获取 lock1lock2)。

  2. 超时机制 使用 ReentrantLock.tryLock(1, TimeUnit.SECONDS) 替代 synchronized,超时后释放已有锁并重试。

可通过 JConsole 或 VisualVM 实时监控线程状态和死锁检测。实际开发中建议使用静态代码分析工具提前发现潜在死锁风险。

死锁产生条件
  • 互斥:synchronized保证锁的互斥性。

  • 持有并等待:线程A持有lock1并等待lock2,线程B持有lock2并等待lock1。

  • 不可抢占:锁只能由持有线程释放。

  • 循环等待:线程A等待线程B,线程B等待线程A。

相关文章:

  • 微信小程序:实现左侧菜单、右侧内容、表单、新增按钮等组件封装
  • 微信小程序传参过来了,但是数据没有获取到
  • 计算机网络学习笔记:TCP可靠传输实现、超时重传时间选择
  • FPGA基础 -- Verilog 禁止语句
  • 电力物联网,5G/4G通讯终端,电力系统通信
  • openstack的实现原理
  • c++读写锁
  • 基于YOLOv10算法的交通信号灯检测与识别
  • Arduino入门教程:11、直流步进驱动
  • 选择标签词汇功能(单选多选),在文本框展示
  • DeepSeek 助力 Vue3 开发:打造丝滑的日历(Calendar),日历_项目里程碑示例(CalendarView01_22)
  • LeetCode 1358.包含所有三种字符的子字符串数目
  • 暑期前端训练day1
  • 前端适配方案之 flexible.js 到 postcss-px-to-viewport-8-plugin插件演进
  • Windows 10开始菜单优化方案,如何实现Win7风格开始菜单的还原
  • 【设计模式】用观察者模式对比事件订阅(相机举例)
  • 【K8S】详解NodePort 和 ClusterIP
  • 【K8S】详解Labels​​ 和 ​​Annotations
  • Android 应用多语言与系统语言偏好设置指南
  • 容器运行时保护:用Falco构建云原生安全防线
  • 旅游外贸网站建设推广/百度站长工具数据提交
  • 焦作网站制作公司/开发网站的公司
  • 网站建设为啥每年都要收费/阐述网络推广的主要方法
  • 博物馆文化网站建设/本周的新闻大事10条
  • 网站建设和源代码问题/百度24小时客服电话136
  • 太原制作手机网站/小红书推广引流