读写锁通过读共享、写独占解决读多写少场景的串行瓶颈,核心是遵守读读不互斥、读写互斥、写写互斥规则,锁内仅做轻量操作并用try-finally确保解锁,非公平模式更优。

读写锁通过让读操作并行、写操作独占,直接解决“读多写少”场景下普通锁的串行瓶颈,从而提升并发度。关键不在加锁本身,而在如何用对规则、避开典型误用。
读锁共享,写锁互斥是并发提升的底层逻辑
普通锁(如 synchronized 或 ReentrantLock)对所有线程一视同仁,读和写都排队——100 个读请求只能一个接一个执行。而 ReentrantReadWriteLock 拆成两把锁:
- 读锁可重入且共享:只要没线程在写,任意数量的读线程能同时进入临界区
- 写锁排他且独占:获取时必须等所有当前读锁释放;持有期间会阻塞新读、新写请求
- 三条互斥规则必须清楚:读读不互斥、读写互斥、写写互斥
锁内只做真正轻量的读/写,否则并发优势归零
锁的作用不是“包住整个方法”,而是精准保护共享状态的访问。耗时操作留在锁外,才能避免拖慢其他线程:
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
- ✅ 读锁内适合:查 HashMap、取 volatile 字段、判断布尔标志
- ❌ 读锁内禁止:远程调用、DB 查询、JSON 序列化、大对象拷贝
- ✅ 写锁内适合:更新 Map、设置字段、校验后写入
- ❌ 写锁内避免:同步发消息、调外部 HTTP、复杂计算(应提前算好再写)
必须用 try-finally 保证解锁,且不能读锁升级写锁
忘记释放锁或错误升级,会导致线程永久阻塞,比不用锁还危险:
立即学习“Java免费学习笔记(深入)”;
- 所有 lock() 后必须配对 unlock(),且放在 finally 块中
- 读锁持有期间调 writeLock().lock() 会死锁——JVM 不支持升级
- 唯一允许的转换是锁降级:先持写锁 → 再获取读锁 → 最后释放写锁,仍保有读锁
- 若读中发现需写,应先释放读锁,再申请写锁(即“双重检查锁定”的变体)
非公平模式更适配大多数生产场景
默认构造的 ReentrantReadWriteLock() 是非公平的,这不是缺陷,而是权衡后的优化:
- 新来的读线程可能插队,略微延长写线程等待,但整体吞吐高 15%~30%
- 公平模式唤醒开销大,且无法缓解“大量读锁长期未释放”导致的写饥饿
- 仅当监控到写锁平均等待超 50ms,才考虑启用公平模式(new ReentrantReadWriteLock(true))

















