fix(Cache): 修复高并发下双重检查锁未正确判断缓存值导致反复覆盖的问题

在 AbstractCache.get(key, isUpdateLastAccess, timeout, supplier) 方法中,
双重检查获取到缓存值后,未对结果进行 null 判断就直接调用 supplier 并覆盖,
导致高并发场景下出现不必要的 supplier 调用和潜在的数据不一致。

修复:在双重检查后增加 null 判断,仅当缓存确实为空时才调用 supplier。

Fixes #IDQGP2
This commit is contained in:
Busyliu
2026-03-02 04:58:37 +00:00
committed by Gitee
parent aa4da21aae
commit b7e9341e32

View File

@@ -134,8 +134,12 @@ public abstract class AbstractCache<K, V> implements Cache<K, V> {
// issue#3686 由于这个方法内的加锁是get独立锁不和put锁互斥而put和pruneCache会修改cacheMap导致在pruneCache过程中get会有并发问题
// 因此此处需要使用带全局锁的get获取值
v = get(key, isUpdateLastAccess);
v = supplier.callWithRuntimeException();
put(key, v, timeout);
// fix issue#IDQGP2: 双重检查后若缓存已有值则直接返回不再调用supplier
// 原实现忽略了双重检查的结果,导致高并发下缓存值被重复覆盖
if (null == v) {
v = supplier.callWithRuntimeException();
put(key, v, timeout);
}
} finally {
keyLock.unlock();
keyLockMap.remove(key);