ReadWriteLock
如果是内部锁、可重入锁,在进行读操作、写操作时,是串行执行的
由于读操作不会对数据产生变更,所以这段串行等待时间可以优化。(读的耗时越多,读写锁的优势更明显)
- 所以在“读-读”、或者“读大于写”的情况下加普通的锁就会影响性能
- 读写锁用的是同一个 Sycn 同步器,因此等待队列、state 等也是同一个。因此读跟写是互斥的
使用注意事项
- 读锁不支持条件变量
重入时升级不支持:即持有读锁的情况下去获取写锁,会导致获取写锁永久等待
class CachedData {
Object data;
// 是否有效,如果失效,需要重新计算 data
volatile boolean cacheValid;
final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
void processCachedData() {
rwl.readLock().lock();
if (!cacheValid) {
// 获取写锁前必须释放读锁
rwl.readLock().unlock();
rwl.writeLock().lock();
try {
// 判断是否有其它线程已经获取了写锁、更新了缓存, 避免重复更新
if (!cacheValid) {
data = ...
cacheValid = true;
}
// 降级为读锁, 释放写锁, 这样能够让其它线程读取缓存
rwl.readLock().lock();
} finally {
rwl.writeLock().unlock();
}
}
rw1.readLock().unlock();
}
}
注意释放写锁是在获取读锁之后,反过来则不行