读写锁概要
读锁是共享锁,写锁是排他锁
公平锁的策略是将锁分配给等待时间最长的锁,因此公平读锁、写锁是不可重入锁?
写锁是排他锁,同一时间段只允许一个线程获取写锁,因此是不可重入锁?
非公平读锁允许多个读线程同时获取读锁,因此是可重入锁?
读锁不能升级为写锁,写锁可以降级为读锁
Condition只能和写锁搭配使用
共享锁和排他锁的相容性
共享锁 | 排他锁 | |
---|---|---|
共享锁 | 〇 | × |
排他锁 | × | × |
官方案例讲解
class CachedData {
Object 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();
}
}
try {
use(data);
} finally {
rwl.readLock().unlock();
}
}
}
class RWDictionary {
private final Map<String, Data> m = new TreeMap<String, Data>();
private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
private final Lock r = rwl.readLock();
private final Lock w = rwl.writeLock();
public Data get(String key) {
r.lock();
try { return m.get(key); }
finally { r.unlock(); }
}
public String[] allKeys() {
r.lock();
try { return m.keySet().toArray(); }
finally { r.unlock(); }
}
public Data put(String key, Data value) {
w.lock();
try { return m.put(key, value); }
finally { w.unlock(); }
}
public void clear() {
w.lock();
try { m.clear(); }
finally { w.unlock(); }
}
}