2 回答

TA貢獻2021條經驗 獲得超8個贊
當您要在一個線程中處理一個類中的多個變量時,是否應該為要鎖定在該類中的每個變量都擁有一個“鎖定對象”?
有兩個規則:
要“細粒度”。擁有盡可能多的鎖,每個變量一個。每次使用它時,都應在其鎖下訪問變量。鎖定盡可能少的代碼以確??缮炜s性。如果忘記鎖定變量,則會導致爭用情況;如果鎖定順序錯誤,則會導致死鎖,因此請確保其完美無缺。
要“粗粒度”。僅擁有一個鎖,然后將所有關鍵部分放在該鎖下。擁有多個鎖可以減少爭用,但會增加死鎖和其他錯誤的可能性,因此鎖應盡可能少,每個鎖中要包含盡可能多的代碼。當然,這也增加了死鎖的風險,因為現在鎖中有很多代碼可以進行倒置,并且降低了可伸縮性。
毫無疑問,標準建議是完全矛盾的。那是因為鎖很糟糕。
我的建議:如果您不跨線程共享變量,則根本不需要任何鎖。
這也是處理線程安全自定義類型的有效方法嗎?
到目前為止,代碼看起來還算合理,但是如果您打算延遲加載某些邏輯,則不要編寫自己的線程邏輯。只需使用Lazy<T>
并使其起作用即可。它是由專家撰寫的。
始終使用專家提供的最高級工具。滾動自己的線程原語是災難的根源。
無論您采取什么措施,都不要采納另一個答案中的建議,即您必須使用雙重檢查鎖定。有沒有什么情況下,你必須使用雙重檢查鎖定。單次檢查鎖定更安全,更容易且更可能正確。僅在以下情況下使用雙重檢查鎖定:(1)您有大量的經驗證據表明爭用是可衡量的,影響用戶的性能問題的原因,該問題將通過低鎖定得到解決,并且(2)您可以解釋C#內存模型使雙重檢查鎖定變得安全。
如果您不能執行(1),那么您就沒有理由進行雙重檢查鎖定;如果您不能執行(2),則不能放心任何安全性。

TA貢獻1785條經驗 獲得超8個贊
您需要使用雙重檢查的鎖定模式。初始化someClass之后,無需獲取someClassLock鎖,將其鎖定在那只會導致不必要的爭用。
if (someClass == null)
{
lock(someClassLock)
{
if (someClass == null)
someClass = new SomeClass();
}
}
您需要內部if塊,因為并發線程可能在第一次空檢查之后但在獲取鎖之前創建了someClass。
當然,您還需要確保以某種本身是線程安全的方式編寫SomeClass,但這將安全地確保僅創建someClass的一個實例。
另一種方法是使用Lazy<T>合適的LazyThreadSafetyMode。
- 2 回答
- 0 關注
- 231 瀏覽
添加回答
舉報