我正在使用下面的代碼,對我來說,似乎競爭條件永遠不會發生在下面的代碼中。或者仍然有比賽條件的機會?當訪問ASP.Net Cache項目時,會繼續導致RACE CONDITION嗎?
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);
}
UPDATE: 克里斯幫我解決這個問題,但我只是想,我會分享一些細節會被他人非常有幫助。爲了完全避免任何競爭條件,我必須在真實部分中添加一個檢查,否則,如果有其他人在緩存中清除了它,我可以以零計數結束List(不刪除該項目,而只是調用在我的if已經評估爲TRUE之後,在Cache中的List對象上清除方法)。那麼,如果在listFromCache對象中,我的真實部分中不會有任何數據。
克服的,在我的原代碼,這種微妙的競爭條件,我必須仔細的真實部分檢查listFromCache如下面的代碼,然後用最新數據重新填充緩存。
而且,克里斯說,如果別人通過調用方法Cache.Remove「刪除」從緩存中的項目,然後將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);
}
不,這不可能在你的評論說,'因爲它是在這一點上的本地引用listFromCache'將成爲空。如果其他地方的緩存項無效,則不會影響本地參考。但是,您可能會得到一個條件,在該條件下您檢索到空值,但在收集文檔('ABC.DataLayer.GetDocuments()')的過程中,另一個進程已經完成並插入了緩存條目,你覆蓋它。 (這對你來說可能是完全可以接受的,在這種情況下,太棒了!) –
你可以嘗試用一個靜態對象鎖定它,但老實說,我不確定這是否會在ASP.NET上下文中工作。我不記得是否所有ASP.NET進程(IIRC,具有不同的靜態上下文)共享「Cache」,或者只在每個Web工作者中共享。如果是後者,靜態鎖定會正常工作。 –
克里斯 - 感謝您的詳細解釋。在ASP.Net中緩存安全的,所以如果兩個用戶插入到緩存中,它將不會發生任何錯誤。但在我的代碼中,如果列表表單緩存不爲空,然後在我到達if(而不是其他部分)的真實部分的時候刪除緩存項。這是我的擔憂。 – Sunil