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