ReentrantReadWriteLock默认非公平易致写饥饿,启用公平模式(new ReentrantReadWriteLock(true))、缩短读锁持有时间、使用tryLock超时重试或StampedLock可有效缓解。

Java 中的 ReentrantReadWriteLock 默认采用“非公平”策略,写线程可能长期抢不到锁,导致写饥饿——尤其在读线程持续高频进入时。要缓解写饥饿,核心是让写线程有机会“插队”或“优先获得调度权”,而非完全依赖排队顺序。
启用公平模式(最直接有效)
构造 ReentrantReadWriteLock 时传入 true,启用公平队列:
- 所有线程(读/写)严格按请求顺序排队,先到先得
- 写线程不会被无限期阻塞在大量新读线程之后
- 代价是吞吐量略降(需维护队列、更多线程唤醒开销)
示例:new ReentrantReadWriteLock(true)
避免读锁长期持有(从源头减少竞争)
写饥饿常源于读操作耗时过长或频繁重入,导致写线程一直等不到空窗期:
立即学习“Java免费学习笔记(深入)”;
- 读操作尽量轻量,不执行 I/O、远程调用或复杂计算
- 不要在读锁内嵌套写锁(会死锁),也不在读锁中长时间等待条件变量
- 考虑用“读锁 + 副本拷贝”替代全程持锁:快速获取快照,释放读锁后再处理
主动让渡或限时等待(写线程可干预)
写线程不必无条件阻塞,可通过以下方式提升响应性:
- 用
tryLock(long, TimeUnit)设置超时,失败后可退避(如Thread.sleep(1))再重试,避免饿死式等待 - 结合
StampedLock的乐观读机制:先尝试无锁读取,仅当验证失败时才升级为读锁,进一步降低读锁占用时间 - 对关键写操作,可设计“写优先信号量”,由写线程触发,临时抑制新读请求(需额外协调逻辑,慎用)
慎用锁升级(读锁 → 写锁)
ReentrantReadWriteLock 不支持锁升级(持有读锁时无法直接获取写锁),若业务误用“先读再判再写”的模式,会因反复释放/争抢加剧饥饿:
- 应改为:先尝试获取写锁;若只需读,再降级为读锁(支持降级)
- 或用
StampedLock的tryConvertToWriteLock(有条件升级,更灵活) - 避免在循环中反复
readLock → unlock → writeLock,这会放大竞争窗口
写饥饿不是锁本身的缺陷,而是使用方式与场景不匹配的结果。公平模式+短读锁+合理重试,三者配合通常就能显著改善。


















