2013-08-07 61 views
3

我正在爲多個項目編寫一個庫。它包含包含和操作數據的類。所以我想我應該這些數據,而這些類的方法執行。但我也想過,如果必須完成線程安全的數據操作,那麼讓更高的應用程序層處理鎖定。稍後將由實際應用程序使用的類的的最佳實踐是什麼。C# - 鎖適合在圖書館中使用的位置?

比方說,我有一個類SpecialList。我該怎麼做:

  • 鎖定數據時方法被稱爲
  • 讓用戶鎖定列表中,如果他需要線程安全+忽略(指數)異常,所以用戶必須趕上他們

如果我知道.NET框架類List如何處理,我會這樣做。


這些類沒有明確針對單線程或多線程。他們只是幫助各種各樣的用途上課。

+2

除非您的列表具有專門針對多線程場景的功能,否則讓所有用戶支付他們可能永遠不需要的鎖都沒有任何意義。 '列表'本身不是線程安全的(在說明文檔中有一個「線程安全」部分)。 – Jon

+0

不,沒有針對多線程的。這是否意味着我在低層我應該避免鎖定? – Bitterblue

+0

是的,你應該避免使用鎖。而只需記錄線程* un * -safety。 –

回答

5

如果您設計的數據結構和類型需要保證線程安全,那麼一定要將鎖和其他構造放入這些類型中以維護這些保證。

但是,單獨的鎖是不夠的。

拿一個簡單的字典。假設您要確保字典內部的數據結構不會被多個線程破壞,所以您需要引入鎖。但是,如果外部的代碼做到這一點:

if (!dict.ContainsKey(key)) 
    dict.Add(key, value); 

再有就是這裏不能保證調用ContainsKeyAdd之間,其他線程尚未加入該密鑰字典。

因此,線程安全類型可能比簡單的鎖需要更多的東西。一種方法,可以在字典操作中安全地將鍵和值添加到字典中,然後返回一個標誌,告訴你它做了什麼,可能是需要的。

其實看這裏:ConcurrentDictionary.TryAdd

我的建議是這樣的:

  1. 如果你需要這些保障,設計通過需要是安全的和可預測的情景將是線程安全的類型,以及實現這些具體
  2. 如果您不需要這些保障,也懶得做任何事情,而不是簡單的記錄,該類型是不是線程安全的,留給使用它

的.NET類型List不代碼以任何方式使用鎖,例如,除了幾個選擇安全線程的地方,特別是SyncRoot property

此外,編寫線程安全的數據類型並不容易。只要在任何需要它們的地方投擲鎖,可能是使它更加線程安全,但是您會在性能方面付出沉重的代價。如果一個程序在使用它時不需要它是線程安全的,那麼您仍然支付大量的價格。

編寫高性能線程安全類型比較困難,通常不依賴於鎖(單獨),而是使用諸如自旋等待,特定CPU指令(其中一些可用於.NET代碼)等等。但是這需要關於現代CPU如何執行代碼的高度專業化的知識。

如果我是你,我會離開線程安全的專家,並從你自己的類型中刪除,除非你絕對需要它。

+0

我看不到線程安全性如何鎖定。你可以給我一些關鍵字來增加鎖定,所以我可以讀更多關於它的內容嗎? – Bitterblue

+0

線程安全!=無數據損壞。線程安全類型實現了必須是線程安全的場景。正如我所說的,檢查ConcurrentDictionary上的TryAdd方法,你也可以使用谷歌的「concurrentdictionary tryadd」並閱讀一些文章。 –

1

我認爲答案取決於你的想要你的庫是否是線程安全的。這看起來微不足道,但這是如何完成的。例如,考慮.NET的集合:

SynchronizedCollection

List(和其他基本的集合 - 不是線程安全的)

所以一個不錯的選擇似乎是在做兩個版本,或者不是線程安全的版本。