新闻详情

新闻详情

首页 / 资讯中心 / 详情

Java进阶篇之ReadWriteLock:让读取并行,让更新保持完整

发布时间:2026/9/30 8:55:22来源:尧图网络
Java进阶篇之ReadWriteLock:让读取并行,让更新保持完整
上一篇通过Condition讨论了“业务条件什么时候满足”。接下来换一个常见场景一份共享数据被频繁查询偶尔更新。所有查询都排成一队有时会浪费并行机会放任读写交错又容易看到更新到一半的数据。ReadWriteLock为这类问题提供了读锁与写锁的配对协议。本文基于Java 21以ReentrantReadWriteLock为例先把访问边界划清再讨论它适合解决什么问题。一、读与写先看操作是否改变共享状态“查询方法”这个名字并不保证方法只读。例如获取数据时顺手更新访问次数、填充缓存就已经包含写操作。划分读写应检查实际行为。不同线程的访问组合是否允许同时持锁读与读可以读与写不可以写与写不可以同一个ReadWriteLock对象管理这一对锁。读路径和写路径若各自创建一个锁对象就失去了共同约束。遵守同一锁协议时写锁释放前的更新对后续获得对应读锁的线程可见。接口契约见Java 21 ReadWriteLock文档。二、把锁边界放在数据结构外层下面用商品目录作教学例子。内部是普通HashMap更新持有写锁读取时在读锁保护下复制快照然后把不可修改的结果交给调用者。图中的并排阅读对应多个读锁持有者等待更新的卡片对应写请求。它是访问规则的示意不表示公平队列中的精确调度顺序。三、完整示例读取快照再更新目录保存为ReadWriteDemo.java使用JDK21运行importjava.util.HashMap;importjava.util.Map;importjava.util.concurrent.*;importjava.util.concurrent.locks.ReentrantReadWriteLock;publicclassReadWriteDemo{staticclassCatalog{privatefinalMapString,IntegerpricesnewHashMap();privatefinalReentrantReadWriteLocklocknewReentrantReadWriteLock();voidput(Stringname,intprice){lock.writeLock().lock();try{prices.put(name,price);}finally{lock.writeLock().unlock();}}MapString,Integersnapshot(){lock.readLock().lock();try{returnMap.copyOf(prices);}finally{lock.readLock().unlock();}}}publicstaticvoidmain(String[]args)throwsException{CatalogcatalognewCatalog();catalog.put(book,42);try(ExecutorServicepoolExecutors.newFixedThreadPool(2)){FutureMapString,Integerfirstpool.submit(catalog::snapshot);FutureMapString,Integersecondpool.submit(catalog::snapshot);System.out.println(reader-1: first.get());System.out.println(reader-2: second.get());pool.submit(()-catalog.put(book,45)).get();System.out.println(after update: catalog.snapshot());}}}javac ReadWriteDemo.javajavaReadWriteDemo输出reader-1: {book42} reader-2: {book42} after update: {book45}这里通过Future.get明确等待两个查询结束再提交更新因此输出便于复现。线程池提供了两个工作线程但这段输出不能证明两次读取在时间上重叠也不能当作性能测试。示例重点是共享数据的访问封装。Map.copyOf在持锁期间复制结构返回后调用者无法修改这个Map。示例的String和Integer也是不可变对象。如果value换成可变对象浅复制仍会共享value引用应进一步复制数据或约束对象的修改方式。四、容易踩坑的地方升级、降级与复查ReentrantReadWriteLock支持写锁降级为读锁持有写锁时先取得读锁再释放写锁。这样从更新转入读取时中间没有允许其他写线程插入的空档。相反线程持有读锁时直接调用writeLock().lock不能完成读锁升级。需要更新时应先释放读锁再竞争写锁拿到写锁后重新检查业务状态。释放与重新获取之间别的线程可能已经完成了更新。具体约束见ReentrantReadWriteLock文档。例如“缓存无效则刷新”的流程应包含两次判断读锁内发现无效释放读锁并取得写锁后再判断是否仍然无效。第二次判断能避免多个线程接连做同一份刷新工作。降级适合“更新后需要继续在保护下使用数据”的情况。如果拿到的是完整不可变快照通常可以释放锁后处理快照结构也更简单。五、使用前再核对四个问题所有访问是否遵守协议不能一部分方法加锁另一部分直接操作内部Map也不要把内部可变集合原样返回。锁内是否有慢操作网络调用、文件访问和耗时计算可能长时间挡住写线程。可以先在锁外准备候选数据再用短写锁提交但提交前要检查版本或前提是否仍成立。读多是否就一定更快读写锁自身也有协调成本。数据很小、读操作极短或写入频繁时收益需要通过贴近实际负载的基准测试确认。本文不提供未经测量的加速比例。是否需要公平性或Condition默认构造是非公平策略可使用new ReentrantReadWriteLock(true)选择公平策略无参数tryLock不会遵守公平排队设置。只有写锁支持newCondition读锁调用会抛出UnsupportedOperationException。这也衔接了上一篇Condition的使用边界。对于独立key更新ConcurrentHashMap可能更合适需要协调多个字段、多个key或整体快照时可以考虑在共同的数据边界上使用读写锁。选择之前先写清楚一次业务操作必须一起保持一致的内容。六、 思维导图ReadWriteLock访问规则读读共享读写互斥数据边界同一对锁快照不泄漏可变状态锁转换写锁可降级释放读锁后重新检查使用取舍缩短持锁时间按实际负载测量七、总结总结要点读写分离的锁协议允许读取共享、更新独占。实际访问必须使用同一对锁内部数据不能从其他路径绕开保护。快照与对象边界同样重要。保护Map结构不等于保护其中所有可变对象返回值也应符合并发约定。锁转换与性能取舍需要具体分析。释放读锁后要复查状态降级按顺序完成是否值得引入读写锁应由实际工作负载验证。下一篇继续讨论StampedLock理解乐观读取为什么需要校验以及它与可重入读写锁的区别。如果你觉得这篇文章对你有所帮助欢迎点赞、收藏、分享
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

Spirula Studio VRAM深度剖析:splat x img类别与位掩码压缩全解,8GB显存训练千万级高斯点 2026/9/30 12:56:05

Spirula Studio VRAM深度剖析:splat x img类别与位掩码压缩全解,8GB显存训练千万级高斯点

Spirula Studio VRAM深度剖析:splat x img类别与位掩码压缩全解,8GB显存训练千万级高斯点 【免费下载链接】spirula-studio Cross-vendor 3D Gaussian Splatting trainer - video to splat to mesh, Vulkan or CUDA. 项目地址: https://gitcode.com/Gi…

阅读更多 →
智能体工程化落地:韧性编排与三道过滤网实战指南 2026/9/30 12:55:58

智能体工程化落地:韧性编排与三道过滤网实战指南

1. 这不是“又一篇综述”,而是一份智能体落地实操手记最近在几个高校实验室和产业项目组里,反复被问到一个问题:“智能体(Agent)到底是不是炒作?我们团队想上手,该从哪切入?论文里那…

阅读更多 →
MacOS、Linux 与 Windows 视频编解码对比:AV1、HEVC、ProRes 与硬件加速优劣势 2026/9/30 12:55:58

MacOS、Linux 与 Windows 视频编解码对比:AV1、HEVC、ProRes 与硬件加速优劣势

在视频播放、转码、剪辑和流媒体场景中,macOS、Linux 和 Windows 的差距主要体现在 硬件加速路径、新编码支持速度、专业格式适配 以及 系统媒体栈成熟度 上。Windows 的优势是硬件和软件兼容面最广;macOS 的优势是 ProRes、HEVC、HDR 色彩管理和 Apple …

阅读更多 →
conda虚拟环境配置CUDA、cuDNN与PyTorch深度学习环境全指南 2026/9/30 12:55:58

conda虚拟环境配置CUDA、cuDNN与PyTorch深度学习环境全指南

说实话,在conda虚拟环境里配置cuda、cudnn和pytorch这套深度学习环境,我已经被同一块石头绊倒过无数次了。每次帮别人排查环境问题,十有八九都是卡在版本对不上、装错位置、或者压根没搞清楚cuda和pytorch之间的对应关系上。这东西真不是靠死…

阅读更多 →
RFID 赋能汽车零部件涂装产线,构建全流程数字化追溯体系 2026/9/30 12:55:58

RFID 赋能汽车零部件涂装产线,构建全流程数字化追溯体系

RFID 赋能汽车零部件涂装产线,构建全流程数字化追溯体系应用背景汽车零部件涂装工序直接决定产品外观质量与防腐性能,是整车制造供应链里关键的一环。当前汽车零部件行业订单呈现多品种、小批量的特点,产线需要支持柔性混线生产,行…

阅读更多 →
55873 正和博弈经济模型:重构数字时代商业价值体系 2026/9/30 12:55:57

55873 正和博弈经济模型:重构数字时代商业价值体系

55873 正和博弈经济模型:重构数字时代商业价值体系本文系统阐述 55873 的正和博弈经济模型 —— 其哲学根基、制度设计、运行机制与价值分配逻辑。参考 ISO/TS 23635:2022《治理指南》、ISO 55013:2024《数据资产管理指南》、ISO/IEC 12791《AI 偏差处理》、联合国《…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉