读写锁分离技术核心是读并行、写独占,适用于读远多于写的缓存场景;需满足读多写少、读操作轻量前提,配合双重检查与锁粒度优化,避免i/o或耗时操作阻塞。

直接用读写锁分离技术,核心是让读操作并行、写操作独占,特别适合缓存这种“读远多于写”的场景。关键不在加锁本身,而在锁的使用方式和配套设计是否匹配业务特征。
明确适用前提:读多写少 + 读操作轻量
读写锁不是银弹。只有当缓存被高频读取(比如每秒数千次)、更新极少(比如配置几分钟才变一次),且读逻辑本身不耗时(如简单查 HashMap、不触发远程调用或复杂计算),才能真正发挥优势。否则读锁共享带来的并发收益会被锁管理开销或长持有时间抵消。
- 典型适用:元数据缓存、静态配置、白名单、权限规则等基本不变但频繁访问的数据
- 明显不适用:实时行情缓存(写太频繁)、含序列化/反序列化的读操作(本身重)、带 DB 回源的 getOrLoad(I/O 阻塞锁)
正确使用 ReentrantReadWriteLock 的基本姿势
必须严格遵循 lock/unlock 成对、try-finally 保障释放,否则容易锁泄漏导致线程阻塞甚至系统卡死。
- 读操作:调用 readLock().lock() → 执行读取 → finally 中 unlock()
- 写操作:调用 writeLock().lock() → 修改数据 → finally 中 unlock()
- 禁止在持有读锁时尝试获取写锁(会抛 UnsupportedOperationException)
- 如需“先读再改”,必须先释放读锁,再抢写锁,并在写锁内二次检查(防止中间被其他线程修改)
进阶优化:结合按需加载避免重复初始化
当缓存为空首次加载时,多个并发读请求可能同时触发加载逻辑,造成资源浪费。用读写锁配合双重检查可安全解决:
- 先用读锁尝试获取缓存值
- 若为空,释放读锁,获取写锁
- 再次检查缓存是否已被其他线程加载(防止重复加载)
- 未加载则执行加载逻辑,完成后放入缓存并释放写锁
这种方式既保证了高并发读的吞吐,又避免了“缓存击穿”和重复加载问题。
注意锁粒度与公平性取舍
默认非公平模式吞吐更高,适合大多数缓存场景;公平模式虽能避免写线程饥饿,但会增加调度开销、降低整体 QPS。除非写操作延迟敏感且写频次不低,否则无需开启公平锁。
- 避免把整个缓存对象用一把读写锁保护——如果缓存是大 Map,可考虑分段锁或更细粒度隔离
- 不要在锁内做任何 I/O、网络调用或耗时计算,否则会把所有等待线程拖慢
- 内存占用略高于普通锁,但对现代 JVM 影响极小,不必过度担忧
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











