我正在使用下面的代码,对我来说,下面的代码似乎永远不会发生竞争条件。还是有可能出现比赛条件?
List<Document> listFromCache = Cache[dataCacheName] as List<Document>;
if (listFromCache != null)
{
//do something with listFromCache. **IS IT POSSIBLE** that listFromCache is
//NULL here
}
else
{
List<Document> list = ABC.DataLayer.GetDocuments();
Cache.Insert(dataCacheName, list, null, DateTime.Now.AddMinutes(5),
System.Web.Caching.Cache.NoSlidingExpiration);
}
更新: 克里斯帮我解决了这个问题,但我只是想,我会分享一些对其他人非常有帮助的细节。
为了完全避免任何竞争条件,我必须在真实部分中添加一个检查,否则我可能会得到一个计数为零的列表,如果其他人在缓存中清除它(不删除该项目,而只需调用 Clear 方法在我的 if 评估为 TRUE 之后,列出缓存中的对象)。那么,在 listFromCache 对象的 if 的真实部分中,我不会有任何数据。
为了克服原始代码中这种微妙的 RACE 条件,我必须仔细检查 listFromCache 的真实部分,如下面的代码所示,然后用最新数据重新填充 Cache。
此外,正如 Chris 所说,如果其他人通过调用 Cache.Remove 方法从 Cache 中“删除”项目,则 listFromCache 不会受到影响,因为垃圾收集器不会从 HEAP 内存中删除实际的 List 对象,因为名为 ' listFromCache' 仍然有它的引用(我在克里斯的回答帖子下的评论中更详细地解释了这一点)。
List<Document> listFromCache = Cache[dataCacheName] as List<Document>;
if (listFromCache != null)
{
//OVERCOME A SUBTLE RACE CONDITION BY IF BELOW
if( listFromCache == null || listFromCache.Count == 0)
{
List<Document> list = ABC.DataLayer.GetDocuments();
Cache.Insert(dataCacheName, list, null, DateTime.Now.AddMinutes(5),
System.Web.Caching.Cache.NoSlidingExpiration);
}
//NOW I AM SURE MY listFromCache contains true data
//do something with listFromCache. **IS IT POSSIBLE** that listFromCache is
//NULL here
}
else
{
List<Document> list = ABC.DataLayer.GetDocuments();
Cache.Insert(dataCacheName, list, null, DateTime.Now.AddMinutes(5),
System.Web.Caching.Cache.NoSlidingExpiration);
}