Java并发编程实战~ReadWriteLock~

快速实现一个缓存

public 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();
	
	// 读缓存
	public V get(K key) {
		r.lock();
		try { 
			return m.get(key); 
		}finally { 
			r.unlock(); 
		}
	}
	
	// 写缓存
	public V put(String key, Data v) {
		w.lock();
		try { 
			return m.put(key, v); 
		}finally { 
			w.unlock(); 
		}
	}
}

实现缓存的按需加载

public 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();
 
  public V getWithLoad(K key) {
    V v = get(key);
    // 缓存中存在,返回
    if(v != null) {  
      return v;
    }  
    
    // 缓存中不存在,查询数据库
    w.lock();      
    try {
      // 再次验证,其他线程可能已经查询过数据库
      v = m.get(key); 
      if(v == null){  
        // 查询数据库
        v= loadData(...);
        m.put(key, v);
      }
    } finally{
      w.unlock();
    }
    return v; 
  }
  
	// 读缓存
	public V get(K key) {
		r.lock();
		try { 
			return m.get(key); 
		}finally { 
			r.unlock(); 
		}
	}
	
}

读写锁的升级与降级

锁的升级--禁止

// 读缓存
r.lock();         
try {
  v = m.get(key); 
  if (v == null) {
    w.lock();
    try {
      // 再次验证并更新缓存
      // 省略详细代码
    } finally{
      w.unlock();
    }
  }
} finally{
  r.unlock();     
}

锁的降级--支持

public class CachedData {
  Object data;
  volatile boolean cacheValid;
  final ReadWriteLock rwl = new ReentrantReadWriteLock();
  // 读锁  
  final Lock r = rwl.readLock();
  // 写锁
  final Lock w = rwl.writeLock();
  
  void processCachedData() {
    // 获取读锁
    r.lock();
    if (!cacheValid) {
      // 释放读锁,因为不允许读锁的升级
      r.unlock();
      // 获取写锁
      w.lock();
      try {
        // 再次检查状态  
        if (!cacheValid) {
          data = ...
          cacheValid = true;
        }
        // 释放写锁前,降级为读锁
        // 降级是可以的
        r.lock(); 
      } finally {
        // 释放写锁
        w.unlock(); 
      }
    }
    // 此处仍然持有读锁
    try {use(data);} 
    finally {r.unlock();}
  }
}
经验分享 程序员 微信小程序 职场和发展