2 回答

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

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