OSCache 缓存重建在 Race Condition 下的 NRE 问题
异常堆栈:
|
java.lang.IllegalStateException: Cannot complete cache update - current state (2) is not UPDATE_IN_PROGRESS at com.opensymphony.oscache.base.EntryUpdateState.completeUpdate(EntryUpdateState.java:105) at com.opensymphony.oscache.base.Cache.completeUpdate(Cache.java:762) at com.opensymphony.oscache.base.Cache.putInCache(Cache.java:619) at com.opensymphony.oscache.base.Cache.putInCache(Cache.java:580) at com.opensymphony.oscache.general.GeneralCacheAdministrator.putInCache(GeneralCacheAdministrator.java:249) at com.opensymphony.oscache.general.GeneralCacheAdministrator.putInCache(GeneralCacheAdministrator.java:259) |
1 String myKey = "myKey"; 2 String myValue; 3 int myRefreshPeriod = 1000; 4 try { 5 // Get from the cache 6 myValue = (String) admin.getFromCache(myKey, myRefreshPeriod); 7 } catch (NeedsRefreshException nre) { 8 try { 9 // Get the value (probably from the database) 10 myValue = "This is the content retrieved."; 11 // Store in the cache 12 admin.putInCache(myKey, myValue); 13 } catch (Exception ex) { 14 // We have the current content if we want fail-over. 15 myValue = (String) nre.getCacheContent(); 16 // It is essential that cancelUpdate is called if the 17 // cached content is not rebuilt 18 admin.cancelUpdate(myKey); 19 } 20 }
即,本线程先试图重建缓存,如果再次发生异常,则本线程(不管三七二十一)直接调用 cancelUpdate 函数。
1 public OSCache get(String key,int myRefreshPeriod){ 2 try{ 3 return (OSCache)this.admin.getFromCache(key,myRefreshPeriod); 4 }catch(NeedsRefreshException ex){ 5 this.admin.cancelUpdate(key); 6 return null; 7 } 8 }
线程1 正在重建缓存;
线程2 读取缓存时得到 NRE 异常,主动 cancel update;
线程1 重建缓存完毕,却发现状态被改为了 UPDATE_CANCELLED ,与期望不符,于是抛出异常 java.lang.IllegalStateException 。
- /**
- * Updates the state to <code>UPDATE_COMPLETE</code>. This should <em>only</em>
- * be called by the thread that managed to get the update lock.
- * @return the counter value after the operation completed
- */
- public int completeUpdate() {
- if (state != UPDATE_IN_PROGRESS) {
- throw new IllegalStateException("Cannot complete cache update - current state (" + state + ") is not UPDATE_IN_PROGRESS");
- }
- state = UPDATE_COMPLETE;
- return decrementUsageCounter();
- }
参考资源:
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
2007-12-07 从digg在新媒体中的角色谈如何定义新媒体
2005-12-07 Midletinfo-探索手机javaME系统信息的实用工具