reentrantreadwritelock通过分离读写锁提升并发性能:读锁共享允许多线程并发读,写锁独占确保写操作互斥;支持锁降级但不支持升级;需在finally中释放锁,可选公平/非公平模式。

ReentrantReadWriteLock 通过分离读写操作的锁,让多个线程可以同时读、但写时独占,从而显著提升读多写少场景下的并发性能。
读写锁的核心分工:读锁共享,写锁互斥
它内部维护一对锁:ReadLock 和 WriteLock。读锁是可重入、共享的——只要没有写锁在持有,任意数量的读线程都能同时进入临界区;写锁则是可重入、排他的——同一时刻最多只有一个写线程能获取,且会阻塞所有读锁请求。这种设计天然适配“读远多于写”的业务,比如缓存查询、配置加载、报表统计等。
- 读操作用
readLock().lock()获取,完成后必须调用unlock() - 写操作用
writeLock().lock()获取,同样需配对解锁 - 不能在持有读锁时直接升级为写锁(会死锁),需先释放读锁再申请写锁
正确使用锁的典型结构:try-finally 保障解锁
忘记释放锁会导致线程永久阻塞,所以务必用 try-finally 包裹临界区。读写锁不支持 lockInterruptibly 的中断语义(除非显式启用公平策略),但基础安全仍是底线。
- 读操作示例:
rwLock.readLock().lock();
try {
return data.get(key); // 安全读取
} finally {
rwLock.readLock().unlock();
}
- 写操作示例:
rwLock.writeLock().lock();
try {
data.put(key, value); // 安全更新
} finally {
rwLock.writeLock().unlock();
}
注意锁降级:写锁 → 读锁 是唯一允许的升级路径
ReentrantReadWriteLock 支持锁降级(downgrading):即在持有写锁期间获取读锁,然后释放写锁,从而继续以读锁保护数据——这能避免写完立刻读时的重复加锁开销和潜在竞态。但反过来(读锁→写锁)绝对禁止,会引发死锁。
- 降级写法要点:必须在同一个线程内,先获取写锁,再获取读锁,最后释放写锁
- 不推荐在读锁未释放时尝试获取写锁,应设计为先释放读锁再争抢写锁
- 若需“读-改-写”逻辑,优先考虑是否能用 CAS 或更轻量的同步机制替代
选择公平性策略:吞吐 vs 响应性
构造时可传入 boolean fair 参数。非公平模式(默认)吞吐更高,但可能饿死长等待线程;公平模式按 FIFO 调度,响应更可预测,适合写操作频繁或对延迟敏感的场景。
- 高并发读场景通常用默认非公平,减少上下文切换开销
- 写操作较重或存在明显长任务时,可启用公平策略防止个别写线程被无限推迟
- 公平锁会带来额外同步开销,实测 QPS 下降约 5%~10%,需权衡
不复杂但容易忽略:锁粒度要匹配业务边界,别把整个 Map 用一把读写锁保护,而应按 key 分段或结合 ConcurrentHashMap 提升伸缩性。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











