修复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);