[英]Will code produce a race condition?
我有一個帶有所有資源基本路徑的文件。 例如:
build/scripts/script1.js
build/scripts/script2.js
我當然需要一個基本路徑,例如:
https://example.org/SuperDuperSite/build/scripts/script1.js
我希望做的是在啟動時使用路徑將文件加載到全局字典中。 該字典僅需加載一次。 不幸的是,據我所知,基本路徑直到第一個請求才可用。 所以在asp.net中,我必須使用application_beginrequest
而不是application_start
。 不好的是,現在我必須處理多線程問題。
這迫使我編寫以下類型的代碼:
lock(_lock) {
if (_dictionary == null) {
LoadDictionary();
}
}
當我只真正需要加載一次時,將為每個請求調用此方法。 我當然不喜歡這樣。 由於性能原因,我不想鎖定每個請求。 與大學討論后,我們提出了一種解決方案:
if (_dictionary == null)
{
lock(_lock) {
if (_dictionary == null) {
LoadDictionary();
}
}
}
因此,使用該解決方案,我不需要在每個請求上都進行鎖定,但是如果多個線程最終在啟動時獲得了本節的內容,那么我將通過再次檢查該對象是否在該鎖內來保護它,從而對其進行保護。 這段代碼會起作用嗎,還是我會遇到競爭狀況?
使用雙重檢查的鎖時要小心。
是的,它是線程安全的,但是在您的特定代碼中,您可能會遇到一個細微的錯誤,其中_dictionary
已由另一個線程實例化 (通過了null
檢查),但尚未完全填充 ,因此您可能最終嘗試訪問a部分填充的字典。 最后是以下兩個之一:
ConcurrentDictionary
(它還帶有性能影響),否則您可能會同時對字典進行讀寫操作,並導致死鎖(是的,眾所周知, Dictionary
類會在許多代碼中導致死鎖)。 在LoadDictionary()
末尾將bool _dictionaryLoaded
標志(仔細檢查)翻轉為true
可能更好。
或者,如果您在.NET 4上,請使用Lazy <> 。它更加LoadDictionary
,您所要做的就是將LoadDictionary
傳遞為init函數。
編輯:Lazy <>在內部使用雙重檢查后的lock實現 。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.