java死锁

文章目录

  • 1、概念
  • 2、解决和预防策略:
    • [1. 按固定顺序获取锁(破坏"循环等待")](#1. 按固定顺序获取锁(破坏“循环等待”))
    • [2. 使用超时机制(破坏"占有并等待")](#2. 使用超时机制(破坏“占有并等待”))
    • [3. 一次性申请所有资源(破坏"占有并等待")](#3. 一次性申请所有资源(破坏“占有并等待”))
  • [3、 死锁检测与恢复](#3、 死锁检测与恢复)

1、概念

死锁是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。这是一个严重的问题,因为死锁会让你的程序挂起无法完成任务,死锁的发生必须满足以下四个条件:

复制代码
互斥条件:一个资源每次只能被一个进程使用。

请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。

不剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺。

循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。

由于"互斥"是锁的基本特性,我们无法破坏它。因此解决方案主要集中在破坏后三个条件。

2、解决和预防策略:

1. 按固定顺序获取锁(破坏"循环等待")

这是最常用、最有效的预防手段。强制所有线程以相同的顺序申请锁。

场景:

比如转账操作,线程 A 从账户 1 转给账户 2,线程 B 从账户 2 转给账户 1。如果一个先锁 1 再锁 2,另一个先锁 2 再锁 1,就容易死锁。

解决:规定一个全局顺序,比如永远先锁 ID 小的账户,再锁 ID 大的账户。

2. 使用超时机制(破坏"占有并等待")

不要让线程无限期地等待锁。如果在指定时间内拿不到锁,就放弃当前操作或稍后重试。

使用 ReentrantLock.tryLock():

java 复制代码
1Lock lock1 = new ReentrantLock();
2Lock lock2 = new ReentrantLock();
3
4// 尝试获取锁,最多等待 1 秒
5if (lock1.tryLock(1, TimeUnit.SECONDS)) {
6    try {
7        if (lock2.tryLock(1, TimeUnit.SECONDS)) {
8            try {
9                // 执行业务逻辑
10            } finally {
11                lock2.unlock();
12            }
13        }
14    } finally {
15        lock1.unlock();
16    }
17}
18// 如果没拿到锁,可以记录日志、重试或返回失败,而不是死锁

使用 synchronized 的替代方案:synchronized 无法设置超时,一旦拿不到锁就会一直阻塞,所以高并发场景建议优先使用 ReentrantLock。

3. 一次性申请所有资源(破坏"占有并等待")

如果一个线程需要多个资源,要么全部申请到,要么一个都不申请。

实现:可以通过一个全局的"资源管理器"来统一分配资源,或者使用 tryLock 尝试获取所有需要的锁,如果有一个获取失败,就释放已获取的锁并重试。

缺点:实现起来比较复杂,可能会降低吞吐量。

3、 死锁检测与恢复

使用 JDK 工具:

  • jstack:在命令行输入 jstack ,如果检测到死锁,JVM
    会直接在控制台输出死锁信息,告诉你哪两个线程在互相等待哪个锁。
  • jconsole / --jvisualvm:图形化界面工具,连接到 Java
    进程后,点击"检测死锁"按钮,能直观地看到死锁的线程和堆栈。
策略 破坏的条件 推荐程度 说明
统一锁顺序 循环等待 ⭐⭐⭐⭐⭐ 最常用,通过排序强制顺序
超时获取锁 占有并等待 ⭐⭐⭐⭐ 使用 ReentrantLock.tryLock()
死锁检测 - ⭐⭐⭐ 发生后及时发现,利用 jstackThreadMXBean
一次性申请 占有并等待 ⭐⭐ 实现复杂,性能可能不高
相关推荐
阿维的博客日记1 小时前
Hippo4j 线程池监控平台部署手册
java·spring boot·后端
南境十里·墨染春水3 小时前
C++ 工厂模式:从入门到进阶,彻底掌握对象创建的艺术
开发语言·c++·算法
C+++Python3 小时前
详细介绍一下Java泛型的通配符
java·windows·python
JosieBook4 小时前
【数据库】时序预测能力的分级进化:TimechoAI如何让每一类用户都能精准预见未来
java·开发语言·数据库
加号34 小时前
【C#】 文件与目录管理:创建、删除操作的技术解析
开发语言·c#
diving deep5 小时前
脚本速览-python
开发语言·python
一生了无挂5 小时前
Java处理JSON技巧教学(从基础到高阶实战全覆盖)
java·开发语言·json
李白的天不白5 小时前
使用 SmartAdmin 进行前后端开发
java·前端
swordbob5 小时前
Spring 单例 Bean 是线程安全的吗?
java·开发语言
2601_951643776 小时前
Python第一,Java跌出前三,C语言杀回来了
java·c语言·python·编程语言排行·技术趋势