修复StampedCache类get方法并发问题(issue#IBCIQG@Gitee)

This commit is contained in:
Looly
2024-12-21 00:46:42 +08:00
parent 9c8dadf600
commit 7467d03fe2
2 changed files with 25 additions and 5 deletions

View File

@@ -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)

View File

@@ -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);