change lock

This commit is contained in:
Looly
2021-01-24 22:37:12 +08:00
parent a8add399c2
commit bdb078b1ee
3 changed files with 19 additions and 9 deletions

View File

@@ -6,6 +6,9 @@ import java.io.Serializable;
import java.util.Iterator;
import java.util.Map;
import java.util.WeakHashMap;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
@@ -24,6 +27,10 @@ public class SimpleCache<K, V> implements Iterable<Map.Entry<K, V>>, Serializabl
private final Map<K, V> cache;
// 乐观读写锁
private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
/**
* 写的时候每个key一把锁降低锁的粒度
*/
protected final Map<K, Lock> keyLockMap = new ConcurrentHashMap<>();
/**
* 构造,默认使用{@link WeakHashMap}实现缓存自动清理
@@ -70,22 +77,24 @@ public class SimpleCache<K, V> implements Iterable<Map.Entry<K, V>>, Serializabl
*/
public V get(K key, Func0<V> supplier) {
V v = get(key);
if(null == v && null != supplier){
lock.writeLock().lock();
try{
v = cache.get(key);
//每个key单独获取一把锁降低锁的粒度提高并发能力see pr#1385@Github
final Lock keyLock = keyLockMap.computeIfAbsent(key, k -> new ReentrantLock());
keyLock.lock();
try {
// 双重检查,防止在竞争锁的过程中已经有其它线程写入
v = cache.get(key);
if (null == v) {
try {
v = supplier.call();
} catch (Exception e) {
throw new RuntimeException(e);
}
cache.put(key, v);
put(key, v);
}
} finally{
lock.writeLock().unlock();
} finally {
keyLock.unlock();
keyLockMap.remove(key);
}
}
@@ -143,4 +152,4 @@ public class SimpleCache<K, V> implements Iterable<Map.Entry<K, V>>, Serializabl
public Iterator<Map.Entry<K, V>> iterator() {
return this.cache.entrySet().iterator();
}
}
}