2013-07-30 36 views
1

我知道何時在C#中使用鎖定塊,但是我不清楚的是鎖定語句括號中的lock variable。考慮以下Singleton Design PatternDoFactory:在上面的代碼C#中的鎖定變量#

class LoadBalancer 
{ 
    private static LoadBalancer _instance; 
    private List<string> _servers = new List<string>(); 
    private static object syncLock = new object(); 
    public static LoadBalancer GetLoadBalancer() 
    { 
    // Support multithreaded applications through 
    // 'Double checked locking' pattern which (once 
    // the instance exists) avoids locking each 
    // time the method is invoked 
    if (_instance == null) 
    { 
    lock (syncLock) 
    { 
     if (_instance == null) 
     { 
     _instance = new LoadBalancer(); 
     } 
    } 
    } 

    return _instance; 
} 
} 

,我不明白爲什麼我們不鎖變量,而不是`SYNCLOCK使用_instance

回答

12

在上面的代碼中,我不明白爲什麼我們不使用_instance作爲lock變量而不是`syncLock?

那麼你會試圖鎖定一個空引用,一方面...

此外,你會通過可變的領域,這是一個壞主意來鎖定。 (如果字段更改值,則另一個線程可以進入相同的代碼,但不是很好)。通過只讀字段進行鎖定通常是個好主意。

此外,你會鎖定一個參考,這是返回給調用者,誰可以持有任意長時間的鎖。我更喜歡鎖定一個永遠不會暴露在課堂外的參考 - 比如syncLock

最後,由於CLI內存模型的原因,這種實現方式仍然存在問題。 (它的可能是或者可能不會在MS實現中被打破,這是更強一點。我不想打賭任何一種方式。)_instance變量應該被標記爲volatile如果你真的想要使用這種方法...但我個人會避免重複檢查鎖定。請參閱我的article on the singleton pattern瞭解更多詳情。

+0

爲什麼編譯器使用syncLock?這個變量有什麼好處? –

+0

@SeyedMortezaMousavi:你是什麼意思「爲什麼編譯器使用syncLock?」它不是編譯器,它是開發人員......關鍵是確保只有一個線程輸入創建LoadBalancer實例的代碼。 –

+2

你需要鎖定一個對象。這就是它的全部。 –

0

我自己並沒有多使用鎖定語句。

但我的猜測是,這是因爲你無法鎖定實例,因爲它是空的。

因此,您必須製作靜態對象「synclock」,該對象僅用於鎖定實際創建「實例」變量的部分。