2011-04-18 48 views
6

我有單獨的對象「服務」和兩個方法來初始化和釋放:爲什麼表達對於'雙重檢查鎖定'總是正確的?

public class BaseService 
{ 
    protected static readonly object StaticLockObject = new object(); 
} 

public abstract class WebServiceBase<TService> : BaseService 
    where TService : System.Web.Services.Protocols.SoapHttpClientProtocol, new() 
{ 
    protected static void EnsureServiceIsOpened() 
    { 
     if (Service == null) 
     { 
      lock (StaticLockObject) 
      { 
       if (Service == null) 
       { 
        Service = new TService(); 
       } 
      } 
     } 
    } 

    protected static void EnsureServiceIsClosed() 
    { 
     if (Service != null) 
     { 
      lock (StaticLockObject) 
      { 
       if (Service != null) // Why expression is always true 
       { 
        Service.Dispose(); 
        Service = null; 
       } 
      } 
     } 
    } 

對於有評論ReSharper的(我用5.1版)顯示一個警告提到的行...

問題1:爲什麼?

問題2:爲什麼它在'EnsureServiceIsOpened'方法中不顯示「類似」消息?

謝謝。

回答

2

這是ReSharper 5.X代碼分析引擎中的bug。 在ReSharper 6.0中修復。

BTW,ReSharper的6帶來了更多的雙鎖模式分析的東西:)

4

Resharper對代碼進行了有限的分析,發現兩個嵌套的if語句檢查完全相同。在單線程環境中,resharper的評論完全正確 - 在第一個if之後,Service將不會是null。當然,在多線程環境中,這不適用,因爲Service可能會從外部改變。在這種情況下,您應該爲resharper註釋代碼或者壓縮此文件的消息,因爲它在多線程環境中不成立。

+0

它不會破壞你的代碼單線程應用程序 - 爲什麼一個*警告*我感到困惑。 :/ – mayu 2013-06-10 02:19:36

+0

因爲可能會發生。代碼分析只能走得這麼遠 - 這就是出現此警告的原因。 – Femaref 2013-06-10 19:50:26

+0

我沒有問題,這是由Resharper顯示,我不認爲這應該是一個警告。 :) – mayu 2013-06-11 02:28:41

3

看來Resharper在這個分析中犯了一個錯誤。由於Service不是局部變量,因此它不知道該表達式總是成立。

第一個版本沒有顯示錯誤的原因很可能是因爲雙重檢查鎖定語言非常常見,而且這是它的通常形式。他們可能爲這種情況進行了測試並刪除了錯誤的警告。

顯示在EnsureServiceIsClosed中的技術不常見,因爲它包含競爭條件。另一個線程可能正在使用Service指示的對象,或處理它之後。如果使用服務的代碼在StaticLockObject上鎖定,但是如果它鎖定了鎖定,那麼這是不可能的,那麼沒有理由在創建和處理對象時進行所有這些雙重檢查鎖定rigamarole。因此,這個代碼是有缺陷的,這是非常確定的。

相關問題