锁(this)和静态对象上的锁之间的区别

时间:2011-07-31 19:19:02

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

以下哪两个代码段更适合使用?

static readonly object _locker = new object();
lock (_locker)

lock (this)

this是当前实例的对象。那么为什么lock (_locker)总是在书中呢?

  

相关:
  What is the difference between lock(this) and lock(thisLock)?
  Why is lock(this) {…} bad?

3 个答案:

答案 0 :(得分:19)

可能会有很大的不同。两者之间最大的区别在于第一个示例使用单个对象锁定(因此static关键字),而第二个示例中的this关键字意味着锁定实例。因此,从性能角度来看,甚至从正确性角度来看,可能会有很大差异,但这取决于锁内部的代码。

当您只需要同步访问实例级别字段时,就不应该使用static关键字,因为这会使代码本身同步,而不是数据(这可能会导致不必要的性能损失)。当然,如果数据本身是静态的(类级数据而不是实例级数据),则需要使用static关键字。另一方面,当您使用this关键字锁定时,当您访问共享/静态资源时,您(当然)会出现正确性问题,因为同步是基于实例的,而多个实例将仍然可以同时访问共享数据。

还有另一个问题,但差异远小于之前提到的差异。第一个示例使用私有声明的对象来锁定,而另一个使用this指针,该指针是对该实例方法本身的对象的引用。由于此引用可供其他对象公开访问,因此它们可能会锁定它,这可能会在极少数情况下导致死锁。如果您是应用程序开发人员,我不会对此感到担心(只要您不锁定System.StringSystem.Type之类的内容),但如果您是框架开发人员,你当然不应该使用lock(this),因为没有办法告诉应用程序开发人员将(ab)使用你的代码的方式。

答案 1 :(得分:8)

锁定私有只读对象几乎总是更可取。

区别在于this通常对外部代码可见,可能会对其进行锁定,即 -

var obj = new YourClass();
lock(obj)
{
    ...
}

...在这种情况下,YourClasslock (this)内的任何尝试都会阻止。

答案 2 :(得分:1)

因为您不希望从对象外部访问锁。

如果你使用lock(this),你可能会陷入僵局:

void blah() {
   lock(this);
   sleep(200);
}

//Some other block of code

MyObject a;
foreach(Mythread m in threads)
{
   lock(a);
   m.Call(a.blah); //Not the best syntax, but you get the idea.
}

如果你将锁保持在对象内,它就不会死锁。