c#锁定传递给方法的引用 - 不好的做法?

时间:2011-08-16 12:57:38

标签: c# .net multithreading locking thread-safety

我的方法类似于:

public static void DoSomething (string param1, string param2, SomeObject o) 
{
   //.....

   lock(o) 
   {
       o.Things.Add(param1);
       o.Update();
       // etc....
   }
}

几点:

  1. 以这种方式锁定不好的做法?
  2. 我应该锁定private static object吗?
  3. 如果是,为什么?

3 个答案:

答案 0 :(得分:20)

为了最大限度地减少副作用,被锁定的对象不应该是被操纵的对象,而应该是指定用于锁定的单独对象。

根据您的要求,有几个选项可以解决此问题:

变体A:私人锁定对象

如果您只是想确保DoSomethingDoSomething的并行实例不冲突,请选择此项。

private static readonly object doSomethingLock = new object();

public static void DoSomething (string param1, string param2, SomeObject o) 
{
   //.....

   lock(doSomethingLock) 
   {
       o.Things.Add(param1);
       o.Update();
       // etc....
   }
}

变式B:将锁定对象作为参数传递

如果o的访问权限即使在DoSomething之外也必须是线程安全的,即,如果其他人编写与DoSomethingElse并行运行的方法DoSomething,则选择此项{1}}并且不得干扰lock中的DoSomething阻止:

public static void DoSomething (string param1, string param2, SomeObject o, object someObjectLock) 
{
   //.....

   lock(someObjectLock) 
   {
       o.Things.Add(param1);
       o.Update();
       // etc....
   }
}

变体C:创建SyncRoot属性

如果您可以控制SomeObject的实现,则可以方便地将锁定对象作为属性提供。这样,您可以实现Variant B而无需传递第二个参数:

class SomeObject
{
    private readonly object syncRoot = new object();

    public object SyncRoot { get { return syncRoot; } }

    ...
}

然后,您只需在lock(o.SyncRoot)中使用DoSomething即可。这是一些BCL类使用的模式,例如Array.SyncLockICollection.SyncRoot

答案 1 :(得分:2)

回答你的第3个问题:

想象一下,后者决定锁定另一个方法参数,可能是:

public void XXX(object o)
{
    lock(o)
    {

    }
}

您将很难尝试查看是否存在死锁。您需要检查作为参数传递给SomeObject的对象o是否永远不会作为参数传递给对象o。

答案 2 :(得分:0)

以下是一个关于如何使用锁的示例:

class Account
{
    decimal balance;
    private Object thisLock = new Object();

    public void Withdraw(decimal amount)
    {
        lock (thisLock)
        {
            if (amount > balance)
            {
                throw new Exception("Insufficient funds");
            }
            balance -= amount;
        }
    }
}

这意味着您锁定一个私有变量的Object,仅用于锁定而不是其他任何东西,

你可以看看这个:

lock Statement (C# Reference)

Thread Synchronization (C# and Visual Basic)