2015-01-12 41 views
4

我有一个关于在C#中锁定的问题。 c#是否锁定对象的实例或成员。锁定实例或成员为基础

如果我有以下代码:

lock(testVar) 
{ 
    testVar = testVar.Where(Item => Item.Value == 1).ToList(); 
    //... do some more stuff 
} 

难道C#中保持锁定,即使我设置testVar到一个新的价值?

+0

为什么你需要重新分配锁? –

+0

@VsevolodGoloviznin你对重新指定锁定有何意义?我重新分配'testVar'。 – BendEg

+1

为什么你使用你正在使用的变量作为锁? –

回答

7

所有C#对象都从System.Object继承,它本身始终包含4个字节,专门用于为lock使用语法糖时使用的字节。这就是所谓的SyncBlock对象

当您使用new,一个新的对象,你的情况,ToList它产生一个新的参照List<T>,你居然首要是旧的参考,你的lock无效。这意味着现在多个线程可能可能在您的lock内。编译器会将您的代码转换为带有额外局部变量的try-finally块,以避免您拍摄腿部。

这就是为什么最佳实践是定义一个专用专用只读变量,它将充当同步根对象,而不是使用类成员。这样,任何读你代码的人都可以清楚你的意图。

编辑:

有一个nice article on MSDN其描述了存储器中的对象结构:

SyncTableEntry还存储一个指向同步块包含有用 信息,而是通过很少需要一个对象的所有实例。这个 信息包括对象的锁,其哈希码,任何thunking 数据,以及它的AppDomain索引。对于大多数对象实例, 将不会为实际SyncBlock分配存储空间,并且syncblk 数字将为零。当执行线程碰到 像lock(obj)或obj.GetHashCode这样的语句时,这将会改变。

Object in memory representation

+1

谢谢你,你的**明确答案! – BendEg

+0

谢谢你的照片,如果我可以的话,我会再给+1。 – BendEg

+1

@BendEg很高兴帮助。我已经添加了MSDN文章的链接。你应该阅读它,有很好的内部见解。 –

4

它可以锁定,表达式(testVar)解析为在物体上。这意味着你的代码确实有线程竞争,因为一旦列表被重新分配,其他并发线程就可能锁定在新的实例上。

一个很好的经验法则:只有lockreadonly字段。 testVar显然不是......但它可能是,特别是如果您使用RemoveAll来更改现有的列表,而不是创建一个新的列表。这当然取决于所有的访问lock内发生的列表。

坦率地说,虽然大多数代码不需要线程安全。如果代码确实需要线程安全,则实现者必须清楚地理解受支持的使用场景。

1

lock表达转换为使用Monitor.Enter/Monitor.Exit一个try/finally表达。 使用类似于您的一些代码(使用VS2015 Preview)进行简单测试,您可以看到编译器将代码转换为的内容。

代码

var testVar = new List<int>(); 
lock (testVar) 
{ 
    testVar = new List<int>(); 
    testVar.Add(1); 
} 

居然被翻译成这样:

List<int> list2; 
List<int> list = new List<int>(); 
bool lockTaken = false; 
try 
{ 
    list2 = list; 
    Monitor.Enter(list2, ref lockTaken); 
    list = new List<int> { 1 }; 
} 
finally 
{ 
    if (lockTaken) 
    { 
     Monitor.Exit(list2); 
    } 
} 

所以你可以看到,编译器已经完全删除您的变量testVar,并与2个变量,即listlist2取而代之。然后会发生以下情况:

  1. list2被初始化为list,现在两个引用指向的List<int>同一个实例。
  2. 呼叫Monitor.Enter(list2, ref lockTaken)在关联与当前线程的List<int>对象同步块。
  3. list变量被分配到的List<int>一个新的实例,但list2仍然指向我们锁定在原来的实例。
  4. 锁是使用list2

所以,即使你认为你换锁变量,你实际上没有释放。但是,这样做会使您的代码难以阅读和混淆,因此您应该使用其他帖子所建议的专用锁定变量。

相关问题