mirror of
https://gitee.com/dromara/hutool.git
synced 2025-04-05 17:20:07 +08:00
修复StampedCache类get方法并发问题(issue#IBCIQG@Gitee)
This commit is contained in:
parent
9c8dadf600
commit
7467d03fe2
@ -2,7 +2,7 @@
|
||||
# 🚀Changelog
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
# 5.8.35(2024-12-19)
|
||||
# 5.8.35(2024-12-21)
|
||||
|
||||
### 🐣新特性
|
||||
* 【poi 】 优化ExcelWriter中使用比较器writer的方法,只对第一条数据进行排序(pr#3807@Github)
|
||||
@ -16,6 +16,7 @@
|
||||
### 🐞Bug修复
|
||||
* 【crypto 】 修复JWTSignerUtil.createSigner中algorithmId未转换问题(issue#3806@Github)
|
||||
* 【core 】 修复DateUtil.rangeContains未重置问题(issue#IB8OFS@Gitee)
|
||||
* 【cache 】 修复StampedCache类get方法并发问题(issue#IBCIQG@Gitee)
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
# 5.8.34(2024-11-25)
|
||||
|
@ -88,7 +88,12 @@ public abstract class StampedCache<K, V> extends AbstractCache<K, V> {
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取值
|
||||
* 获取值,使用乐观锁,但是此方法可能导致读取脏数据,但对于缓存业务可容忍。情况如下:
|
||||
* <pre>
|
||||
* 1. 读取时无写入,不冲突,直接获取值
|
||||
* 2. 读取时无写入,但是乐观读时触发了并发异常,此时获取同步锁,获取新值
|
||||
* 4. 读取时有写入,此时获取同步锁,获取新值
|
||||
* </pre>
|
||||
*
|
||||
* @param key 键
|
||||
* @param isUpdateLastAccess 是否更新最后修改时间
|
||||
@ -97,10 +102,24 @@ public abstract class StampedCache<K, V> extends AbstractCache<K, V> {
|
||||
*/
|
||||
private V get(K key, boolean isUpdateLastAccess, boolean isUpdateCount) {
|
||||
// 尝试读取缓存,使用乐观读锁
|
||||
CacheObj<K, V> co = null;
|
||||
long stamp = lock.tryOptimisticRead();
|
||||
CacheObj<K, V> co = getWithoutLock(key);
|
||||
if (false == lock.validate(stamp)) {
|
||||
// 有写线程修改了此对象,悲观读
|
||||
boolean isReadError = true;
|
||||
if(lock.validate(stamp)){
|
||||
try{
|
||||
// 乐观读,可能读取脏数据,在缓存中可容忍,分两种情况
|
||||
// 1. 读取时无线程写入
|
||||
// 2. 读取时有线程写入,导致数据不一致,此时读取未更新的缓存值
|
||||
co = getWithoutLock(key);
|
||||
isReadError = false;
|
||||
} catch (final Exception ignore){
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
if(isReadError){
|
||||
// 转换为悲观读
|
||||
// 原因可能为无锁读时触发并发异常,或者锁被占(正在写)
|
||||
stamp = lock.readLock();
|
||||
try {
|
||||
co = getWithoutLock(key);
|
||||
|
Loading…
Reference in New Issue
Block a user