C#线程锁定并使用锁定对象;锁定对象的正确范围应该是什么?

时间:2011-03-16 05:02:00

标签: c# multithreading locking

使用声明为类的字段而不是本地范围的锁定对象之间是否存在差异?

例如:在以下示例中使用lockObject1lockObject2之间有区别吗?

public class Test()
{
   private Object lockObject1 = new Object();

   public void FooBar()
   {
       lock(lockObject1)
       {
          //Thread safe area 1
       }

       var lockObject2 = new Object();
       lock(lockObject2)
       {
           //Thread safe area 2
       }
   }
}

似乎大多数示例似乎总是瞥见选择锁定对象的范围的重要性。

4 个答案:

答案 0 :(得分:8)

本地锁对象实际上不会提供任何线程安全性,因为运行FooBar的多个线程都将拥有自己的对象,而不是共享单个对象进行锁定。 (可悲的是,在我提出问题并及时纠正之前,我已经在编写代码的过程中看到了这个问题。)

答案 1 :(得分:4)

如果要锁定对象的所有实例,则应始终使用私有静态成员变量。如果要锁定特定的实例,请使用非静态私有成员。

永远不要使用公开可见的成员或'this',因为你永远不知道别人何时会将它用于自己的锁定,并可能导致死锁。

public class Test()
{
   private static Object lockObjectAll = new Object();
   private Object lockObjectInstance = new Object();

   public void FooBar()
   {
       lock (lockObjectAll)
       {
          // Thread safe for all instances
       }

       lock (lockObjectInstance)
       {
          // Thread safe for 'this' instance
       }
   }
}

答案 2 :(得分:2)

你的lockObject2不会保护任何东西,因为它不会被锁定在其他任何地方。请注意,不同线程对FooBar的多次调用将不受保护,因为每次调用FooBar时它都是一个新实例。另外,请注意lockObject1并不是更好。它允许在同一实例上的调用之间进行锁定。如果只访问成员变量,这很好。但是,如果正在访问某些全局资源,则lockObject1将无法完全保护,因为该类的每个实例都有自己的实例。正如@Haoest所建议的那样,使lockObject1 static应该可以解决这个问题。

答案 3 :(得分:1)

将lockObject1设为静态,你应该没问题。

lockObject2也应该是静态字段才有效。