2009-12-11 88 views
2

是否有共同的方式來「共享」在同一組數據上運行的不同對象之間的鎖?C#與多線程共享鎖

我知道有一個公共對象鎖定通常不建議。

例如,隊列可以實現爲線程安全,但其他一些類可能需要特定的鎖才能鎖定多個隊列操作。如果我有第三個類,那麼還需要在這個Queue實例上進行多個鎖定操作?

例如: (比方說L<T>是線程安全的名單,只是爲了節省一些打字)

class Worker 
{ 
    private readonly L<Something> _list; 
    public Worker(L<Something> list) { _list = list; } 

    private readonly object _lock = new object(); 
    public void Replace(Something old, Something new) 
    { 
     lock (_lock) 
     { 
      if (_list.Contains(old)) 
      { 
       _list.Remove(old); 
       _list.Add(new); 
      } 
     } 
    } 
} 

如果其他類,在不同的線程中,只是在移除old元素if條件下,列表將不再包含該元素,因爲_lock是一個私有對象。

我應該鎖定實際的列表實例嗎?

回答

8

常見的方法是公開一個屬性,如ICollection.SyncRoot。當然,大家必須服從鎖定才能工作。

如果你可以避免這種情況,並按照ck的建議封裝操作,那將會更加健壯和易於理解。

+0

謝謝,這是我的問題的正確答案:共享鎖的常用方法。我意識到這些影響,但只是想看看是否有第三種可能性,我不知道。 – Groo 2009-12-11 15:28:13

9

不要將此列表作爲屬性公開,只能與其交互。然後,您可以處理一個類中的所有鎖定,而不處理公共鎖定對象。

+0

我明白你的觀點,但在這種情況下,所有與這些數據交互的方法必須屬於同一個類。你不能有一個不同的類來完成一系列的操作,而且也是線程安全的。 – Groo 2009-12-11 15:08:53

+0

@Robert - 你知道你可以自己編輯帖子,對吧? – Groo 2009-12-11 15:10:10

+0

@Groo re:羅伯特格蘭特 - 可以,他是一個當地的傻瓜。 – cjk 2009-12-11 15:17:50

4

從技術上講,您可以輕鬆地公開鎖定對象。這樣做的問題在於,不讓他們公開的建議的真正原因是僵局。

如果鎖對象被暴露出來,它會帶來一些其他代碼會鎖定在這個對象上而不考慮鎖定順序的風險。這反過來可能導致死鎖。

即使鎖沒有明確暴露,也存在相同的危險。

最好的方法是根本不公開鎖 - 既不隱式也不明確。換句話說,將他們完全埋葬在提供服務的班級中。不幸的是,有時這不是一種選擇。