针对读多写少,JDK提供了ReadWriteLock,容易使用且性能较好;读写锁允许多个线程读共享变量,只允许一个线程写共享变量,如果一个线程写共享变量时,禁止读线程读共享变量
实现实例 -- 按需加载的缓存实现
class Cache<K,V> {
final Map<K, V> m = new HashMap<>();
final ReadWriteLock rwl = new ReentrantReadWriteLock();
final Lock r = rwl.readLock();
final Lock w = rwl.writeLock();
V get(K key) {
V v = null;
//读缓存
r.lock(); ①
try {
v = m.get(key); ②
} finally{
r.unlock(); ③
}
//缓存中存在,返回
if(v != null) { ④
return v;
}
//缓存中不存在,查询数据库
w.lock(); ⑤
try {
//再次验证
//其他线程可能已经查询过数据库
v = m.get(key); ⑥
if(v == null){ ⑦
//查询数据库
v=省略代码无数
m.put(key, v);
}
} finally{
w.unlock();
}
return v;
}
}
原理实现
读写状态的设计
读写锁需要在同步状态上维护多个读线程和一个写线程

读写状态的确认:如果当前同步状态值为S,S不等于0当写状态等于0,读状态不等于0时,获取读锁
写锁的获取与释放
写锁是一个支持重进入的排他锁,如果当前线程已经获取写锁,增加写状态。如果当前线程在获取,如果当前线程在获取写锁时,读锁已经被获取,或者该线程不是已经获取写锁的线程,则当前线程进入等待状态
读锁的获取与释放
读锁是一个支持重进入的共享锁,它能够被多个线程同时获取;在没有其他线程访问时,读锁会被成功的获取,增加读状态,如果当前线程已经获取锁,则增加读状态,如果当前线程在获取读锁时,写锁已经被其他线程获取,则进入等待状态
