lock(this) 和 lock(thisLock) 有什么区别?

8

我正在阅读 lock语句 (C# 参考),其中我看到了这段代码:

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

    //...

    int Withdraw(int amount)
    {
        lock (thisLock)
        {
           //....
        }
    }

    //...
}

我在想,如果我们在上面的例子中写 lock(this) 而不是 lock(thisLock),是否会有任何不同。 如果您的答案取决于它,请查看完整示例
如果您认为lock(this)lock(thisLock)之间确实有区别,则请帮助我理解其中的所有重要点的区别。 特别地,每个究竟意味着什么?

3
可能是为什么lock(this) {...}不好?的重复问题。 - Hans Passant
2个回答

14
成因在于,如果误用lock,可能会导致线程死锁。如果你不知道锁定目标的可见性(也就是说,你无法确定谁拥有对目标的引用以及它们何时会执行lock),那么你无法确切知道应用程序是否会经历死锁。
因此,习惯上锁定一个private成员:因为它是私有的并且在你的代码中,你知道没有其他人可以锁定它。
当然,这通常是一种纯理论上的区别(通常人们不会随意锁定任意对象),但这是一种良好的防御性编程实践。
你链接到的页面说明了:
一般情况下,避免锁定公共类型或超出你代码控制范围的实例。常见的构造锁定(lock) (this)、lock(typeof(MyType))和 lock("myLock")违反这个准则:
* 如果该实例可以公开访问,锁定(this)将是个问题,因为其他人可能使用他们拥有的引用锁定该实例,而你采用lock(this)的代码当然不会预料到这种情况。(参见IDEone上的示例,看第26行)。
* 如果MyType是公开可访问的,那么锁定(typeof(MyType))将成为一个问题。这就是上面情况的变体,如果该类型对其他代码可见,那么你可能会尝试锁定与该代码相同的实例( typeof返回单例实例)。
* 锁定("myLock")也是有问题的,因为进程中使用相同字符串的任何其他代码都将共享同一个锁。由于字符串插值,代码可能最终尝试锁定同一个实例。
最佳实践是定义一个私有对象来锁定,或者定义一个私有静态字段来锁定(C# 6.0以上版本)。静态对象变量用于保护所有实例共享的数据。

我不理解这句话的意思:“and your code that does lock(this) will of course not expect that.” 为什么会导致死锁? - Nawaz
@Nawaz:添加了一个示例。它能清晰地说明问题吗? - Jon
1
我仍然不理解死锁。为什么线程X不能在线程Y完成对“obj”上锁的关键代码执行后,开始执行lock(this){}内部的代码? - Nawaz

2
当你使用lock(this)时,你并不能完全控制this,因为你不知道谁还会使用this或者你的类的实例。使用本地对象是安全的,因为该本地对象仅在你的类内部可用,因此你将完全控制它。
有关详细信息,请参见此处

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接