ReentrantReadWriteLock 是 Java 中支持读写分离的可重入锁,允许多读单写,适用于读多写少场景;其核心是读锁共享、写锁独占,支持锁降级但禁止锁升级,使用需显式加解锁并避免常见陷阱。

ReentrantReadWriteLock 是 Java 并发包中用于实现读写分离的经典工具,它允许多个线程同时读、但写操作独占,适合“读多写少”的场景(比如缓存、配置中心、状态快照等)。
理解读写锁的基本行为
ReentrantReadWriteLock 内部维护一对锁:一个读锁(共享锁)、一个写锁(排他锁)。关键规则如下:
- 读锁可被多个线程同时持有,只要没有线程持有写锁
- 写锁是独占的,获取时要求既无其他写锁,也无任何读锁在持有中
- 读锁和写锁不可重入交叉:已持读锁的线程不能直接获取写锁(会死锁),反之亦然
- 支持公平/非公平模式,默认是非公平(吞吐高,但可能饥饿)
基础用法:声明与加锁释放
使用时需显式获取和释放锁,推荐用 try-finally 确保释放,避免泄漏:
private final ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
private final Lock readLock = rwLock.readLock();
private final Lock writeLock = rwLock.writeLock();
// 读操作
public String getValue() {
readLock.lock();
try {
return data; // 安全读取共享变量
} finally {
readLock.unlock();
}
}
// 写操作
public void setValue(String value) {
writeLock.lock();
try {
data = value;
} finally {
writeLock.unlock();
}
}
注意锁降级(Lock Downgrading)的正确姿势
ReentrantReadWriteLock 支持“锁降级”——即先获取写锁,再获取读锁,最后释放写锁,从而让当前线程继续持有读锁。这是唯一允许的锁升级/降级方式,常用于“先修改后安全读”的场景(如刷新缓存后立即读取新值):
立即学习“Java免费学习笔记(深入)”;
- 必须按顺序:写锁 → 读锁 → 释放写锁(不能释放读锁后再操作)
- 不能反过来(读锁→写锁):会导致阻塞甚至死锁
- 示例:更新配置后立刻读取最新值,且希望后续读操作能并发进行
正确降级写法:
writeLock.lock();
try {
updateData(); // 修改数据
readLock.lock(); // 升读锁(此时写锁仍持有)
} finally {
writeLock.unlock(); // 释放写锁,保留读锁
}
// 此时当前线程仍持有读锁,可安全读;其他线程也可并发读
// … 使用完后记得手动 unlock readLock
实用建议与常见陷阱
实际使用中需避开几个典型问题:
- 不要在 synchronized 块内嵌套 ReentrantReadWriteLock:混合使用易引发死锁或语义混乱
- 读锁不保护写操作:仅靠 readLock 无法阻止其他线程并发写,务必确保所有写路径都走 writeLock
- 避免锁粒度过大:例如在 readLock 临界区内做耗时 IO 或复杂计算,会阻塞其他读线程,削弱并发优势
- 考虑是否真需要读写锁:若写操作极少且读操作本身很轻量,用 volatile 或 CopyOnWriteArrayList 可能更简单高效



















