2

我经常看到这个:

object lockObj;
List<string> myStrs;

// ...

lock(lockObj)
{
    myStrs.Add("hello world");
}

为什么要有单独的对象?当然你可以这样做:

List<string> myStrs;

// ...

lock(myStrs)
{
    myStrs.Add("hello world");
}
4

5 回答 5

5

仅当myStrs是 public 时直接在列表上锁定是一个问题,因此也可以被其他调用者锁定,从而导致可能的死锁。

如果是私人成员,那应该没有问题,但无论如何锁定一个单独的成员object是一个好习惯。

请参阅此类似问题以获得更详细的答案: 为什么 lock(this) {...} bad?

于 2012-12-28T13:49:22.323 回答
2

通常,避免锁定公共类型或超出代码控制范围的实例。常见的构造 lock (this)、lock (typeof (MyType)) 和 lock ("myLock") 违反了此准则:

  1. 如果实例可以公开访问,lock (this) 是一个问题。
  2. 如果 MyType 可公开访问,则 lock (typeof (MyType)) 是一个问题。
  3. lock(“myLock”) 是一个问题,因为进程中使用相同字符串的任何其他代码都将共享相同的锁。

最佳实践是定义一个私有对象来锁定,或者一个私有静态对象变量来保护所有实例共有的数据。

形成文档锁 c#

于 2012-12-28T14:05:55.710 回答
0

您的字符串列表是用于内部实现细节的列表。

如果您更改实现以重新初始化字符串列表的方式,则第二个版本的问题可能会上升。

那么你的实现的线程安全性可能会被破坏。

因此,最好使用单独的对象进行同步并将该对象声明为只读。

于 2012-12-28T13:51:13.760 回答
0

这个想法是始终锁定只能由我们正在查看的代码访问的私有成员。而当我们锁定我们无法控制的成员(如公共成员或类似成员)时,很可能代码的其他部分已经可以锁定。这可能会导致意外的阻塞行为。

所以,我认为这导致了经验法则/拥有私有对象的最佳实践,特别是用于锁定。

我很想看看是否还有更多原因。

于 2012-12-28T13:55:30.040 回答
0

如果将列表用作锁定对象,并将其重置为null,则 lock(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();
}
于 2012-12-28T14:04:45.887 回答