C# 在访问ASP.Net缓存项时,下列内容是否会导致竞争条件?
我正在使用下面的代码,对我来说,下面的代码似乎永远不会出现竞争条件。还是还有机会保持比赛状态C# 在访问ASP.Net缓存项时,下列内容是否会导致竞争条件?,c#,asp.net,caching,C#,Asp.net,Caching,我正在使用下面的代码,对我来说,下面的代码似乎永远不会出现竞争条件。还是还有机会保持比赛状态 List<Document> listFromCache = Cache[dataCacheName] as List<Document>; if (listFromCache != null) { //do something with listFromCache. **IS IT POSSIBLE** th
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);
}
List listFromCache=Cache[dataCacheName]作为列表;
if(listFromCache!=null)
{
//对listFromCache执行操作。**是否可能**listFromCache
//此处为空
}
其他的
{
List List=ABC.DataLayer.GetDocuments();
Insert(dataCacheName,list,null,DateTime.Now.AddMinutes(5),
System.Web.Caching.Cache.NoSlidingExpiration);
}
更新:
Chris帮我解决了这个问题,但我只是想,我会分享一些对其他人非常有帮助的细节
为了完全避免任何竞争条件,我必须在true部分中添加一个检查,否则,如果在我的if计算为true后,其他人在缓存中清除列表(不是删除该项,而是在缓存中的List对象上调用Clear方法),我可能会得到一个计数为零的列表。因此,在listFromCache对象中,if的真实部分中不会有任何数据
为了克服这个微妙的竞争条件在我的原始代码中,我必须像下面的代码一样仔细检查listFromCache的真实部分,然后用最新的数据重新填充缓存
此外,正如Chris所说,如果其他人通过调用Cache.Remove方法从缓存中“删除”项,则listFromCache不会受到影响,因为垃圾收集器不会从堆内存中删除实际的List对象,因为名为“listFromCache”的变量仍有对它的引用(我在Chris的回复帖子下的评论中对此进行了更详细的解释)
List listFromCache=Cache[dataCacheName]作为列表;
if(listFromCache!=null)
{
//克服一个微妙的种族条件,如果下面
if(listFromCache==null | | listFromCache.Count==0)
{
List List=ABC.DataLayer.GetDocuments();
Insert(dataCacheName,list,null,DateTime.Now.AddMinutes(5),
System.Web.Caching.Cache.NoSlidingExpiration);
}
//现在我确信我的listFromCache包含真实的数据
//对listFromCache执行操作。**是否可能**listFromCache
//此处为空
}
其他的
{
List List=ABC.DataLayer.GetDocuments();
Insert(dataCacheName,list,null,DateTime.Now.AddMinutes(5),
System.Web.Caching.Cache.NoSlidingExpiration);
}
不,在您的注释中,listFromCache
不可能变为null,因为此时它是一个本地引用。如果缓存项在其他地方为null,则不会影响您的本地引用。但是,您可能会遇到这样一种情况,即在收集文档的过程中检索到null值s(ABC.DataLayer.GetDocuments()
)另一个进程已经这样做并插入了缓存项,此时您可以覆盖它。(这对您来说可能是完全可以接受的,在这种情况下,太好了!)
您可以尝试使用静态对象锁定它,但老实说,我不确定这在ASP.NET上下文中是否有效。我不记得缓存是在所有ASP.NET进程(IIRC具有不同的静态上下文)之间共享的,还是仅在每个web worker内共享的。如果是后者,则静态锁定可以正常工作 也只是为了证明:
List<Document> listFromCache = Cache[dataCacheName] as List<Document>;
if (listFromCache != null)
{
Cache.Remove(dataCacheName);
//listFromCache will NOT be null here.
if (listFromCache != null)
{
Console.WriteLine("Not null!"); //this will run because it's not null
}
}
List listFromCache=Cache[dataCacheName]作为列表;
if(listFromCache!=null)
{
Cache.Remove(dataCacheName);
//listFromCache在此不为空。
if(listFromCache!=null)
{
Console.WriteLine(“NOTNULL!”);//这将运行,因为它不是null
}
}
不,在您的注释中,listFromCache
不可能变为null,因为此时它是一个本地引用。如果缓存项在其他地方为null,则不会影响您的本地引用。但是,您可能会遇到这样一种情况,即在收集文档的过程中检索到null值s(ABC.DataLayer.GetDocuments()
)另一个进程已经这样做并插入了缓存项,此时您可以覆盖它。(这对您来说可能是完全可以接受的,在这种情况下,太好了!)
您可以尝试使用静态对象锁定它,但老实说,我不确定这在ASP.NET上下文中是否有效。我不记得缓存是在所有ASP.NET进程(IIRC具有不同的静态上下文)之间共享的,还是仅在每个web worker内共享的。如果是后者,则静态锁定可以正常工作 也只是为了证明:
List<Document> listFromCache = Cache[dataCacheName] as List<Document>;
if (listFromCache != null)
{
Cache.Remove(dataCacheName);
//listFromCache will NOT be null here.
if (listFromCache != null)
{
Console.WriteLine("Not null!"); //this will run because it's not null
}
}
List listFromCache=Cache[dataCacheName]作为列表;
if(listFromCache!=null)
{
Cache.Remove(dataCacheName);
//listFromCache在此不为空。
if(listFromCache!=null)
{
Console.WriteLine(“NOTNULL!”);//这将运行,因为它不是null
}
}
否,您的注释中不可能出现listFromCache
将变为null的情况,因为此时它是一个本地引用。如果缓存项在其他地方为null,则不会影响您的本地引用。但是,您可能会遇到这样的情况,即在收集文档的过程中检索到null值(ABC.DataLayer.GetDocuments()
)另一个进程已经这样做并插入了缓存项,此时您可以覆盖它。(这对您来说是完全可以接受的,在这种情况下,太好了!)您可以尝试使用静态对象锁定它,但老实说,我不确定这是否适用于ASP.NET上下文。我不记得是在所有ASP.NET进程(IIRC具有不同的静态上下文)中共享Cache
,还是仅在每个单独的ASP.NET进程中共享