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
一次性申请 占有并等待 ⭐⭐ 实现复杂,性能可能不高
相关推荐
向上的车轮3 分钟前
为什么.NET(C#)转 Java 开发时常常在“吐槽”Java:checked exception
java·c#·.net
Dragon Wu4 分钟前
Spring Security Oauth2.1 授权码模式实现前后端分离的方案
java·spring boot·后端·spring cloud·springboot·springcloud
island13147 分钟前
CANN GE(图引擎)深度解析:计算图优化管线、内存静态规划与异构任务的 Stream 调度机制
开发语言·人工智能·深度学习·神经网络
跳动的梦想家h10 分钟前
环境配置 + AI 提效双管齐下
java·vue.js·spring
坚持就完事了12 分钟前
Java中的集合
java·开发语言
魔芋红茶16 分钟前
Python 项目版本控制
开发语言·python
wjhx20 分钟前
QT中对蓝牙权限的申请,整理一下
java·数据库·qt
YCY^v^25 分钟前
JeecgBoot 项目运行指南
java·学习
云小逸31 分钟前
【nmap源码解析】Nmap OS识别核心模块深度解析:osscan2.cc源码剖析(1)
开发语言·网络·学习·nmap
冰暮流星31 分钟前
javascript之二重循环练习
开发语言·javascript·数据库