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

本文关键字:区别 对象 this 静态 | 更新日期: 2023-09-27 18:04:00

下面两个代码片段哪一个更好使用?

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

lock (this)

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

相关:
lock(this)和lock(thisLock)的区别是什么?
为什么lock(this) {…}不好?

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

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

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

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

锁住私有只读对象几乎总是可取的。

不同之处在于this通常对外部代码可见,外部代码可能会对其加锁,即-

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

…在这种情况下,任何在YourClasslock (this)之间的尝试都会被阻塞。

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

如果你使用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.
}

如果你把锁放在对象里面,它就不会死锁