reentrantreadwritelock 是 java 中支持读共享、写互斥的可重入读写锁,适用于读多写少场景;其读锁允许多线程并发获取,写锁独占且需无读写锁占用;使用需成对 lock/unlock,支持锁降级但禁止升级,非公平模式默认,读锁不支持条件变量,适用高并发读、低频写、强一致性场景。

ReentrantReadWriteLock 是 Java 并发包中用于实现读写分离锁的核心工具,它允许多个线程同时读、但写操作独占,从而在读多写少场景下显著提升并发性能。
读写锁的基本分工:读锁共享,写锁互斥
ReentrantReadWriteLock 内部维护一对锁:ReadLock 和 WriteLock。它们共用同一个同步状态,但行为不同:
- ReadLock(读锁):可被多个线程同时获取,只要没有线程持有写锁;一旦有线程正在写,后续读请求需等待
- WriteLock(写锁):完全互斥,同一时刻最多一个线程能持有;获取写锁时,必须确保当前无任何读锁或写锁被占用
这种设计天然适配“读多写少”的业务场景(如缓存、配置中心、报表统计),避免了传统 synchronized 或 ReentrantLock 导致的读操作排队阻塞。
典型使用方式:分别获取读锁/写锁并正确释放
关键在于锁的获取与释放必须成对,且推荐用 try-finally 保证释放安全:
Java JDK 25 来自 OpenJDK 官方归档,版本为 JDK 25,本条下载地址已指向官方 Windows x64 zip 安装包直链,适合调试旧项目或兼容旧版 Java 运行环境。
- 读操作:先 lock() 读锁,处理完数据后 unlock()
- 写操作:先 lock() 写锁,修改完数据后 unlock()
示例代码片段:
private final ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
private final Lock readLock = rwLock.readLock();
private final Lock writeLock = rwLock.writeLock();
private Map<string object> cache = new HashMap();
// 读方法
public Object get(String key) {
readLock.lock();
try {
return cache.get(key);
} finally {
readLock.unlock();
}
}
// 写方法
public void put(String key, Object value) {
writeLock.lock();
try {
cache.put(key, value);
} finally {
writeLock.unlock();
}
}
</string>
进阶注意点:避免常见误用陷阱
实际使用中容易忽略几个关键细节:
- 锁降级可行,锁升级禁止:允许先获取写锁、再获取读锁(即“降级”),用于写后立即读的场景;但不能先持读锁再尝试获取写锁,会导致死锁
-
非公平模式是默认行为:ReentrantReadWriteLock 默认是非公平锁(可能让新来的写线程插队),若需严格按请求顺序,构造时传入
true启用公平模式(但会降低吞吐) - 读锁不支持条件变量:只有 WriteLock 支持 newCondition(),读锁调用会抛 UnsupportedOperationException
- 锁绑定的是线程,不是调用栈:同一线程可重入多次读锁或写锁,但每次 lock() 都要对应一次 unlock()
适用边界:什么时候不该用读写锁?
并非所有读多写少场景都适合 ReentrantReadWriteLock:
- 如果读操作本身非常轻量(比如只读一个 volatile 字段),加锁开销反而高于收益
- 写操作频繁(例如写占比超 10%),读锁的获取/释放和状态检查成本会上升,此时普通可重入锁可能更稳
- 存在复杂嵌套读写逻辑,或需要跨多个资源协调,建议优先考虑更高级抽象(如 StampedLock 或事务型数据结构)
简单说:它优化的是“高并发读 + 低频写 + 数据一致性要求强”的场景,不是万能银弹。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










