mirror of
https://gitee.com/dromara/hutool.git
synced 2025-04-05 17:37:59 +08:00
修复AbstractCache.get中锁不一致导致的并发问题
This commit is contained in:
parent
74ee2c7425
commit
5e680123a7
@ -29,6 +29,7 @@
|
|||||||
* 【core 】 修复Convert.digitToChinese(0)输出金额无`元整问题`(issue#3662@Github)
|
* 【core 】 修复Convert.digitToChinese(0)输出金额无`元整问题`(issue#3662@Github)
|
||||||
* 【core 】 修复CsvParser中对正文中双引号处理逻辑问题(pr#1244@Gitee)
|
* 【core 】 修复CsvParser中对正文中双引号处理逻辑问题(pr#1244@Gitee)
|
||||||
* 【core 】 修复ZipUtil.zip压缩到本目录时可能造成的死循环问题(issue#IAGYDG@Gitee)
|
* 【core 】 修复ZipUtil.zip压缩到本目录时可能造成的死循环问题(issue#IAGYDG@Gitee)
|
||||||
|
* 【cache 】 修复AbstractCache.get中锁不一致导致的并发问题(issue#3686@Github)
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------
|
||||||
# 5.8.29(2024-07-03)
|
# 5.8.29(2024-07-03)
|
||||||
|
@ -2,7 +2,6 @@ package cn.hutool.cache.impl;
|
|||||||
|
|
||||||
import cn.hutool.cache.Cache;
|
import cn.hutool.cache.Cache;
|
||||||
import cn.hutool.cache.CacheListener;
|
import cn.hutool.cache.CacheListener;
|
||||||
import cn.hutool.core.exceptions.ExceptionUtil;
|
|
||||||
import cn.hutool.core.lang.func.Func0;
|
import cn.hutool.core.lang.func.Func0;
|
||||||
import cn.hutool.core.lang.mutable.Mutable;
|
import cn.hutool.core.lang.mutable.Mutable;
|
||||||
import cn.hutool.core.lang.mutable.MutableObj;
|
import cn.hutool.core.lang.mutable.MutableObj;
|
||||||
@ -130,18 +129,13 @@ public abstract class AbstractCache<K, V> implements Cache<K, V> {
|
|||||||
keyLock.lock();
|
keyLock.lock();
|
||||||
try {
|
try {
|
||||||
// 双重检查锁,防止在竞争锁的过程中已经有其它线程写入
|
// 双重检查锁,防止在竞争锁的过程中已经有其它线程写入
|
||||||
final CacheObj<K, V> co = getWithoutLock(key);
|
// issue#3686 由于这个方法内的加锁是get独立锁,不和put锁互斥,而put和pruneCache会修改cacheMap,导致在pruneCache过程中get会有并发问题
|
||||||
if (null == co || co.isExpired()) {
|
// 因此此处需要使用带全局锁的get获取值
|
||||||
try {
|
v = get(key, isUpdateLastAccess);
|
||||||
v = supplier.call();
|
if (null == v) {
|
||||||
} catch (Exception e) {
|
// supplier的创建是一个耗时过程,此处创建与全局锁无关,而与key锁相关,这样就保证每个key只创建一个value,且互斥
|
||||||
// issue#I7RJZT 运行时异常不做包装
|
v = supplier.callWithRuntimeException();
|
||||||
throw ExceptionUtil.wrapRuntime(e);
|
|
||||||
//throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
put(key, v, timeout);
|
put(key, v, timeout);
|
||||||
} else {
|
|
||||||
v = co.get(isUpdateLastAccess);
|
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
keyLock.unlock();
|
keyLock.unlock();
|
||||||
|
Loading…
Reference in New Issue
Block a user