0

0

Java里的ReentrantReadWriteLock锁降级怎么做_读写锁转换规则

P粉602998670

P粉602998670

发布时间:2026-03-07 03:57:29

|

398人浏览过

|

来源于php中文网

原创

java里的reentrantreadwritelock锁降级怎么做_读写锁转换规则

锁降级在 ReentrantReadWriteLock 中根本不能直接做

ReentrantReadWriteLock 不支持“写锁降级为读锁”以外的任何降级操作,而且这个“降级”也不是原子动作——它只是你手动释放写锁、再获取读锁的过程。很多人以为调用某个函数就能自动完成,其实没有 downgrade() 这种方法,更不存在 tryConvertToReadLock()

常见错误现象是:线程持有写锁后,试图不释放就调用 readLock().lock(),结果被自己阻塞(因为写锁还没放,读锁无法重入);或者误以为 writeLock().unlock() 后读锁会“继承”写锁的持有权,导致数据被其他线程修改。

  • 必须先 writeLock().unlock(),再 readLock().lock()
  • 中间不能有非原子操作(比如网络请求、日志打印),否则降级窗口期可能被其他写线程抢占
  • 如果多个线程都走这套流程,得靠外部同步或额外状态位控制,否则可能读到过期值

为什么非要“先解锁再加读锁”而不是设计成原子操作

这是 ReentrantReadWriteLock 的设计取舍:它把锁语义和线程调度完全交给 JVM,不引入跨锁状态机。写锁和读锁底层共享同一个 AQS state 字段,但 bit 位划分固定(高16位读计数,低16位写重入计数),没法在不破坏 state 含义的前提下“切换类型”。

性能上,强制原子降级需要在 AQS 中增加额外 CAS 循环和状态校验,反而拖慢高频写场景;兼容性上,老版本 JDK(如 6/7)的 AQS 实现也不支持这种扩展。

立即学习Java免费学习笔记(深入)”;

XAnswer
XAnswer

XAnswer是一款可以生成思维导图的AI搜索工具,聚合全网优质信息源,结合LLM能力和RAG技术, 为用户提供实时性的搜索结果、个性化的答案呈现。

下载
  • 读写锁共用 Sync 内部类,state 没有预留“过渡态”空间
  • tryAcquireShared()tryAcquire() 是两个独立入口,无共享上下文
  • JDK 官方文档明确说:“Lock downgrading is supported... by acquiring the read lock before releasing the write lock”——注意是“before releasing”,不是“while holding”

正确实现锁降级的三步写法(带防御)

典型场景:更新缓存后立刻读取,希望避免写锁释放后被其他线程覆盖。关键不是“怎么写”,而是“怎么防断层”。

示例中 cache 是 volatile 引用,data 是实际内容,降级前需确保引用已更新且可见:

// 假设 data 已计算完毕
writeLock.lock();
try {
    cache = data; // volatile 写,保证可见性
} finally {
    writeLock.unlock(); // 必须在这里释放
}
// ↓ 降级窗口开始:此时 cache 可能已被其他线程改写
readLock.lock();
try {
    return cache; // 读取最新值(可能是别人刚写的)
} finally {
    readLock.unlock();
}
  • volatile 写必须在 writeLock.unlock() 前完成,否则读线程看不到更新
  • 不能把 readLock.lock() 放进 writeLock 的 try 块里——编译器可能重排序,JVM 不保证锁释放顺序
  • 如果业务要求“必须读到自己刚写的值”,就得放弃降级,改用纯写锁 + 多次读,或引入版本号校验

容易被忽略的线程安全破口

最常翻车的地方不是锁本身,而是降级后对共享对象的访问方式。ReentrantReadWriteLock 只管锁的获取与释放,不管对象内部是否线程安全。

比如你降级后拿到一个 ConcurrentHashMap 引用,以为“读锁保护了整个 map”,其实没用——读锁只保护你获取引用的动作,map 里面的 put()computeIfAbsent() 还是各自加自己的锁。

  • 降级后调用 cache.get(key) 是安全的,但 cache.put(key, v) 会触发新的写操作,必须重新申请写锁
  • 如果 cacheArrayList,即使持有读锁,调用 get(0) 也可能抛 ConcurrentModificationException(除非你确认没人并发修改结构)
  • 锁降级不传递 happens-before 关系到对象字段,所以字段级 volatile 或 final 修饰不能省

事情说清了就结束

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
while的用法
while的用法

while的用法是“while 条件: 代码块”,条件是一个表达式,当条件为真时,执行代码块,然后再次判断条件是否为真,如果为真则继续执行代码块,直到条件为假为止。本专题为大家提供while相关的文章、下载、课程内容,供大家免费下载体验。

104

2023.09.25

c++中volatile关键字的作用
c++中volatile关键字的作用

本专题整合了c++中volatile关键字的相关内容,阅读专题下面的文章了解更多详细内容。

75

2025.10.23

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

743

2023.08.10

golang map内存释放
golang map内存释放

本专题整合了golang map内存相关教程,阅读专题下面的文章了解更多相关内容。

77

2025.09.05

golang map相关教程
golang map相关教程

本专题整合了golang map相关教程,阅读专题下面的文章了解更多详细内容。

39

2025.11.16

golang map原理
golang map原理

本专题整合了golang map相关内容,阅读专题下面的文章了解更多详细内容。

67

2025.11.17

java判断map相关教程
java判断map相关教程

本专题整合了java判断map相关教程,阅读专题下面的文章了解更多详细内容。

47

2025.11.27

JavaScript浏览器渲染机制与前端性能优化实践
JavaScript浏览器渲染机制与前端性能优化实践

本专题围绕 JavaScript 在浏览器中的执行与渲染机制展开,系统讲解 DOM 构建、CSSOM 解析、重排与重绘原理,以及关键渲染路径优化方法。内容涵盖事件循环机制、异步任务调度、资源加载优化、代码拆分与懒加载等性能优化策略。通过真实前端项目案例,帮助开发者理解浏览器底层工作原理,并掌握提升网页加载速度与交互体验的实用技巧。

1

2026.03.06

Rust内存安全机制与所有权模型深度实践
Rust内存安全机制与所有权模型深度实践

本专题围绕 Rust 语言核心特性展开,深入讲解所有权机制、借用规则、生命周期管理以及智能指针等关键概念。通过系统级开发案例,分析内存安全保障原理与零成本抽象优势,并结合并发场景讲解 Send 与 Sync 特性实现机制。帮助开发者真正理解 Rust 的设计哲学,掌握在高性能与安全性并重场景中的工程实践能力。

19

2026.03.05

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Kotlin 教程
Kotlin 教程

共23课时 | 4.2万人学习

C# 教程
C# 教程

共94课时 | 10.8万人学习

Java 教程
Java 教程

共578课时 | 77.8万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号