我看到這個有很多:使用一個單獨的對象進行同步
object lockObj;
List<string> myStrs;
// ...
lock(lockObj)
{
myStrs.Add("hello world");
}
爲什麼有單獨的對象?當然,你可以只是這樣做:
List<string> myStrs;
// ...
lock(myStrs)
{
myStrs.Add("hello world");
}
我看到這個有很多:使用一個單獨的對象進行同步
object lockObj;
List<string> myStrs;
// ...
lock(lockObj)
{
myStrs.Add("hello world");
}
爲什麼有單獨的對象?當然,你可以只是這樣做:
List<string> myStrs;
// ...
lock(myStrs)
{
myStrs.Add("hello world");
}
它是直接在列表僅myStrs
是公衆對鎖定的問題,因此可以通過其他調用被鎖定爲好,從而可能導致死鎖。
如果是私人會員,那麼應該沒有問題,但鎖定在單獨的object
是任何情況下的良好習慣。
進行更詳細的解答看到這個類似的問題: Why is lock(this) {...} bad?
你的字符串列表是用於內部實現細節的清單。
如果您改變您的實現以使您重新初始化字符串列表,則第二個版本的問題可能會增加。
然後你的實現的線程安全性可能被破壞。
因此,最好使用單獨的對象進行同步並將此對象聲明爲只讀。
這個想法是總是鎖定一個只能被我們正在查看的代碼訪問的私人成員。而當我們鎖定那些我們沒有控制權的成員像公共成員或類似人員時,可能會有其他部分代碼已經擁有鎖定。這可能會導致意外的阻止行爲。
所以,我認爲這導致了拇指規則/最佳做法是擁有專用於鎖定的私人對象。
我想查看是否有更多原因出現。
如果您使用列表作爲鎖定對象,並將其重置爲null,那麼鎖定(myStringList)將引發ArgumentNullException。在控制檯應用程序的簡單測試代碼下面。
private static IList<string> mystringList = new List<string>();
static void Main(string[] args)
{
new Thread(() =>
{
try
{
while (true)
{
//Acquire the lock
lock (mystringList)
{
//Do something with the data
Thread.Sleep(100);
Console.WriteLine("Lock acquired");
}
}
}
catch (Exception exception)
{
Console.WriteLine("Exception: " +exception.Message);
}
}).Start();
new Thread(() =>
{
//Suppose we do something
Thread.Sleep(1000);
//And by some how reset the list to null
mystringList = null;
}).Start();
Console.ReadLine();
}
一般情況下,避免鎖定在一個公共類型,或者超出你的代碼的控制情況。共同構建鎖(本),鎖(typeof運算(的MyType)),並鎖定(「myLock」)違反此準則:
- 鎖(這)是一個問題,如果該實例可以公開訪問。
- 如果MyType是可公開訪問的,則鎖定(typeof(MyType))是一個問題。
- 鎖(「myLock」)是一個問題,因爲使用相同字符串的進程中的任何其他代碼將共享相同的鎖。
最佳做法是定義要鎖定的私有對象或私有靜態對象變量以保護所有實例共有的數據。
表格文檔lock c#
+1 - 這些都是大問題 - 主要是整個「如果別人能看到的東西,我鎖定在,別人可以搶我的鎖」點;這裏提到的使用字符串有雙重危險,因爲字符串通常是被實現的,因此所有相同的字符串實際上是同一個對象。 – JerKimball