基於ReadWriteLock讀寫鎖實現的緩存

package william.pattern;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.function.Supplier;

/**
 * @Author: ZhangShenao
 * @Date: 2019/5/22 10:22
 * @Description:基於讀寫鎖實現的簡單的緩存
 * 1.讀操作之間可併發執行
 * 2.讀寫、寫寫操作之間互斥
 * 3.根據key獲取不同的鎖,減小鎖粒度
 */
public class SimpleCache<K, V> {
    private Map<K, V> cache = new HashMap<>();
    private Map<K, ReadWriteLock> locks = new ConcurrentHashMap<>();

    public V get(K key, Supplier<V> optionsWhenMiss) {
        V value;
        try {
            //加讀鎖
            acquireLock(key, false);

            //查詢緩存
            value = cache.get(key);
        } finally {
            //釋放讀鎖
            releaseLock(key, false);
        }

        //如果緩存命中,則直接返回
        if (value != null) {
            return value;
        }

        //緩存未命中,加寫鎖,執行optionsWhenMiss操作
        try {
            acquireLock(key, true);
            //這裏再進行一次緩存的查詢,避免高併發場景下,多線程競爭寫鎖,導致數據的重複查詢
            value = cache.get(key);
            if (value == null) {
                value = optionsWhenMiss.get();
            }
        } finally {
            //釋放寫鎖
            releaseLock(key, true);
        }
        return value;
    }

    public void put(K key, V value) {
        //加寫鎖
        try {
            acquireLock(key, true);
            cache.put(key, value);
        } finally {
            //釋放寫鎖
            releaseLock(key, true);
        }
    }

    private void acquireLock(K key, boolean write) {
        Lock lock = lockForKey(key, write);
        lock.lock();
    }

    private void releaseLock(K key, boolean write) {
        Lock lock = lockForKey(key, write);
        lock.unlock();

    }

    private Lock lockForKey(K key, boolean write) {
        ReadWriteLock rw = locks.computeIfAbsent(key, k -> new ReentrantReadWriteLock());
        return write ? rw.writeLock() : rw.readLock();
    }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章