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

@ -14,6 +14,7 @@
* 【core 】 修正LocalDateTimeUtil.offset方法注释问题issue#I2EEXC@Gitee * 【core 】 修正LocalDateTimeUtil.offset方法注释问题issue#I2EEXC@Gitee
* 【extra 】 VelocityEngine的getRowEngine改为getRawEngineissue#I2EGRG@Gitee * 【extra 】 VelocityEngine的getRowEngine改为getRawEngineissue#I2EGRG@Gitee
* 【cache 】 缓存降低锁的粒度提高并发能力pr#1385@Github * 【cache 】 缓存降低锁的粒度提高并发能力pr#1385@Github
* 【core 】 SimpleCache缓存降低锁的粒度提高并发能力pr#1385@Github
### Bug修复 ### Bug修复
* 【core 】 修复FileUtil.move以及PathUtil.copy等无法自动创建父目录的问题issue#I2CKTI@Gitee * 【core 】 修复FileUtil.move以及PathUtil.copy等无法自动创建父目录的问题issue#I2CKTI@Gitee

View File

@ -150,7 +150,7 @@ public abstract class AbstractCache<K, V> implements Cache<K, V> {
final Lock keyLock = keyLockMap.computeIfAbsent(key, k -> new ReentrantLock()); final Lock keyLock = keyLockMap.computeIfAbsent(key, k -> new ReentrantLock());
keyLock.lock(); keyLock.lock();
try { try {
// 双重检查锁 // 双重检查锁防止在竞争锁的过程中已经有其它线程写入
final CacheObj<K, V> co = cacheMap.get(key); final CacheObj<K, V> co = cacheMap.get(key);
if (null == co || co.isExpired()) { if (null == co || co.isExpired()) {
try { try {

View File

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