2013-05-21 64 views
4

圖片驗證碼:如何防止死鎖,當你需要鎖定多個對象

你有2個數組,你需要在同一時刻,他們都鎖定(以任何理由 - 你只需要保持鎖定他們兩人,因爲他們已經在某種程度上取決於對方) - 你可以窩鎖

lock (array1) 
{ 
    lock (array2) 
    { 
     ... do your code 
    } 
} 

,但是這可能會導致死鎖的情況下,有人在你的代碼的其他部分會做

lock (array2) 
{ 
    lock (array1) 
    { 
     ... do your code 
    } 
} 

和數組1被鎖定 - 執行上下文切換 - 然後數組2被第二個線程鎖定。

有沒有辦法自動鎖定它們?如

lock_array(array1, array2) 
{ 
    .... 
} 

我知道我可能只是創造一些額外的「鎖定對象」,並鎖定這不是兩個數組無處不在我的代碼,但是這似乎並不正確,我...

+4

創建一個額外的鎖對象*是*正確的。 –

+0

使用將鎖定這兩個項目的單個鎖定對象是要走的路。 – user871289

回答

5

一般來說,您應該避免鎖定可公開訪問的成員(您的案例中的數組)。你寧願有一個private static object你會鎖定。

+0

你能否詳述一下?我不明白你的意思。如果這是需要公開提供的東西,像一些全球陣列 – Petr

+1

該陣列可以公開,這不是問題。你應該鎖定的內容不應該公開。所以在你的類中定義一個'private static object syncRoot = new object();'然後鎖定它:'lock(syncRoot){...對數組做些什麼...}。 –

+1

好 - 但是如果我從其他一些沒有訪問syncRoot的對象訪問這個公共數組,我該如何鎖定它?我在閱讀時如何防止數組被修改? – Petr

1

我不確定你的意思是鎖定到數組。 您可以輕鬆地在單鎖中對兩個陣列執行操作。

static readonly object a = new object(); 
lock(a){ 
    //Perform operation on both arrays 
    } 
4

你應該永遠不要鎖定可公開訪問的變量,如Darin所說。例如

public class Foo 
{ 
    public object Locker = new object(); 
} 

public class Bar 
{ 
    public void DoStuff() 
    { 
     var foo = new Foo(); 
     lock(foo.Locker) 
     { 
      // doing something here 
     } 
    } 
} 

而是做這樣的事情。

public class Foo 
{ 
    private List<int> toBeProtected = new List<int>(); 
    private object locker = new object(); 

    public void Add(int value) 
    { 
     lock(locker) 
     { 
      toBeProtected.Add(value); 
     } 
    } 
} 

原因是如果您有多個線程訪問多個公共同步構造,然後運行死鎖的真實可能性。那麼你必須非常小心你的代碼。如果你正在讓你的圖書館可用於其他人,你可以確保你可以抓住鎖?也許有人使用你的圖書館也抓住了鎖,並且你們兩人之間已經陷入僵局。這是Microsoft推薦不使用SyncRoot的原因。