ReadWriteLock缓存

     读写锁使用原则:

一个共享变量允许同时被多个读线程读取到
一个共享变量在同一时刻只能被一个写线程进行写操作
一个共享变量在被写线程执行写操作时,这个共享变量不能被读线程执行读操作

   在读写锁中,读锁调用newCondition()会抛出UnsupportedOperationException异常,读锁不支持条件变量。

      按需查询缓存的业务

class ReadWriteLockCache<K,V> {
    private final Map<K, V> m = new HashMap<>();
    private final ReadWriteLock rwl =  new ReentrantReadWriteLock();
    private final Lock r = rwl.readLock();
    private 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; 
    }
}

   get()方法中从缓存中读取数据,对查询缓存的操作添加读锁,查询返回后,进行解锁操作。判断缓存中返回的数据是否为空,不为空,则直接返回数据;如果为空,则获取写锁,之后再次从缓存中读取数据,如果缓存中不存在数据,则查询数据库,将结果数据写入缓存,释放写锁。最终返回结果数据

  如果有三个线程同时调用get()方法,同时运行到 w.lock(),由于写锁的排他性。只有一个线程会获取到写锁,其他两个线程则阻塞在w.lock()处。获取到写锁的线程继续往下执行查询数据库,将数据写入缓存,之后释放写锁。另外两个线程竞争写锁,某个线程会获取到锁,继续往下执行,如果在w.lock()后没有v = m.get(key); 再次查询缓存的数据,则这个线程会直接查询数据库,将数据写入缓存后释放写锁。

  在ReadWriteLock中,锁是不支持升级的,因为读锁还未释放时,此时获取写锁,就会导致写锁永久等待,相应的线程也会被阻塞而无法唤醒。

class CachedData {
    Object data;
    volatile boolean cacheValid;
    final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();

    void processCachedData() {
        rwl.readLock().lock();
        if (!cacheValid) {
            // Must release read lock before acquiring write lock
            rwl.readLock().unlock();
            rwl.writeLock().lock();
            try {
                // Recheck state because another thread might have
                // acquired write lock and changed state before we did.
                if (!cacheValid) {
                    data = ...
                    cacheValid = true;
                }
                // Downgrade by acquiring read lock before releasing write lock
                rwl.readLock().lock();
            } finally {
                rwl.writeLock().unlock(); // Unlock write, still hold read
            }
        }

        try {
            use(data);
        } finally {
            rwl.readLock().unlock();
        }
    }
}}

 

  

  

   

posted on 2022-04-20 13:52  溪水静幽  阅读(40)  评论(0)    收藏  举报