簡體   English   中英

代碼會產生競爭條件嗎?

[英]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部分填充的字典。 最后是以下兩個之一:

  1. 閱讀字典時您錯過了結果,或更糟糕的是
  2. 除非您使用ConcurrentDictionary (它還帶有性能影響),否則您可能會同時對字典進行讀寫操作,並導致死鎖(是的,眾所周知, Dictionary類會在許多代碼中導致死鎖)。

LoadDictionary()末尾將bool _dictionaryLoaded標志(仔細檢查)翻轉為true可能更好。

或者,如果您在.NET 4上,請使用Lazy <> 。它更加LoadDictionary ,您所要做的就是將LoadDictionary傳遞為init函數。

編輯:Lazy <>在內部使用雙重檢查后的lock實現

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM