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();
}
}
基於ReadWriteLock讀寫鎖實現的緩存
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.