如果您設計的數據結構和類型需要保證線程安全,那麼一定要將鎖和其他構造放入這些類型中以維護這些保證。
但是,單獨的鎖是不夠的。
拿一個簡單的字典。假設您要確保字典內部的數據結構不會被多個線程破壞,所以您需要引入鎖。但是,如果外部的代碼做到這一點:
if (!dict.ContainsKey(key))
dict.Add(key, value);
再有就是這裏不能保證調用ContainsKey
和Add
之間,其他線程尚未加入該密鑰字典。
因此,線程安全類型可能比簡單的鎖需要更多的東西。一種方法,可以在字典操作中安全地將鍵和值添加到字典中,然後返回一個標誌,告訴你它做了什麼,可能是需要的。
其實看這裏:ConcurrentDictionary.TryAdd。
我的建議是這樣的:
- 如果你需要這些保障,設計通過需要是安全的和可預測的情景將是線程安全的類型,以及實現這些具體
- 如果您不需要這些保障,也懶得做任何事情,而不是簡單的記錄,該類型是不是線程安全的,留給使用它
的.NET類型List
不代碼以任何方式使用鎖,例如,除了幾個選擇安全線程的地方,特別是SyncRoot property。
此外,編寫好線程安全的數據類型並不容易。只要在任何需要它們的地方投擲鎖,可能是使它更加線程安全,但是您會在性能方面付出沉重的代價。如果一個程序在使用它時不需要它是線程安全的,那麼您仍然支付大量的價格。
編寫高性能線程安全類型比較困難,通常不依賴於鎖(單獨),而是使用諸如自旋等待,特定CPU指令(其中一些可用於.NET代碼)等等。但是這需要關於現代CPU如何執行代碼的高度專業化的知識。
如果我是你,我會離開線程安全的專家,並從你自己的類型中刪除,除非你絕對需要它。
除非您的列表具有專門針對多線程場景的功能,否則讓所有用戶支付他們可能永遠不需要的鎖都沒有任何意義。 '列表'本身不是線程安全的(在說明文檔中有一個「線程安全」部分)。 –
Jon
不,沒有針對多線程的。這是否意味着我在低層我應該避免鎖定? – Bitterblue
是的,你應該避免使用鎖。而只需記錄線程* un * -safety。 –