public class Cache<K, V> { private final Map<K, V> map = new HashMap<>(); private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock(); // 读锁 private final Lock readLock = readWriteLock.readLock(); // 写锁 private final Lock writeLock = readWriteLock.writeLock(); // 读缓存 -- 懒加载 public V get(K key) { V v = null; // 读缓存 readLock.lock(); // 1 try { v = map.get(key); // 2 } finally { readLock.unlock(); // 3 } // 缓存中存在,直接返回 if (v != null) { // 4 return v; } // 缓存中不存在,查询数据库 writeLock.lock(); // 5 try { // 再次验证,其他线程可能已经查询过数据库了 // 避免在高并发场景下重复查询数据库的问题 v = map.get(key); // 6 if (v == null) { // 7 // 查询数据库 v = loadFromDb(key); map.put(key, v); } } finally { writeLock.unlock(); } return v; } private V loadFromDb(K key) { return null; } // 写缓存 public V put(K key, V value) { writeLock.lock(); try { return map.put(key, value); } finally { writeLock.unlock(); } } }
ReadWriteLock不支持锁升级,readLock还没有释放,无法获取writeLock,导致 线程阻塞
readLock.lock(); try { V v = map.get(key); if (v == null) { writeLock.lock(); try { map.put(key, loadFromDb(key)); } finally { writeLock.unlock(); } } } finally { readLock.unlock(); }
readLock.lock(); if (!cacheValid) { // 因为不允许读锁升级,先释放读锁 readLock.unlock(); writeLock.lock(); try { if (!cacheValid) { cacheValid = true; } // 释放写锁前,降级为读锁,这是允许的 readLock.lock(); // 1 } finally { writeLock.unlock(); } } // 此时仍然持有读锁 try { // 使用数据 } finally { readLock.unlock(); }
转载请注明出处:http://zhongmingmao.me/2019/05/09/java-concurrent-readwrite-lock/
访问原文「 Java并发 -- ReadWriteLock 」获取最佳阅读体验并参与讨论