C# 为什么需要冗余锁对象?

C# 为什么需要冗余锁对象?,c#,multithreading,locking,C#,Multithreading,Locking,出于好奇,我正在查看MSDN上的lock关键字: class Account { decimal balance; private Object thisLock = new Object(); public void Withdraw(decimal amount) { lock (thisLock) { if (amount > balance) {

出于好奇,我正在查看MSDN上的
lock
关键字:

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

    public void Withdraw(decimal amount)
    {
        lock (thisLock)
        {
            if (amount > balance)
            {
                throw new Exception("Insufficient funds");
            }
            balance -= amount;
        }
    }
}

在上面的示例中,对象
thisLock
lock
关键字一起使用。为什么需要这样做?它似乎没有任何其他用途。为什么不让
lock
关键字单独存在呢?

lock
关键字本身不能存在,它总是使用一个参数作为信号量(同步对象),只允许一个线程继续

只有一个线程可以锁定同步对象(在本例中, 每次锁定一次,所有争用线程都会被阻塞,直到释放锁为止。如果有多个线程争用锁,则它们是 在“就绪队列”上排队,并在先到时授予锁, 先到先得(警告是 Windows和CLR意味着队列的公平性有时会受到影响 (被侵犯)


这里有几个方面:

  • lock
    语句需要一个对象引用作为标识符。它必须有一些东西来标识这个锁,并将它与代码中可能存在的任何其他锁分开

  • 您要保护的数据不是引用类型,因此需要使用其他内容作为锁的标识符

  • 建议使用仅用作锁标识符的私有对象,即使可以将数据本身用作标识符。这样,就没有理由在类外公开引用,因为如果引用在类外的锁中使用,则可能会出现死锁


用于锁定的对象不是多余的。该对象充当一个令牌,用于实现一个简单的同步协议:持有锁的人被授予访问锁定代码的权限。所有其他人都必须等到锁被释放


如果没有对象,就不可能有不同的令牌,所有同步都将依赖于单个内部令牌。这将不会非常有效

lock关键字本身将是无效的C#。你在考虑
lock(this){…}
?我认为理论上,C语言/编译器可以允许类似
lock()
的语法,这将为特定的锁处理一个唯一的对象。但是会引起一些可用性问题,例如:锁是静态的还是实例级的?更不用说,在意外放置
lock()
而不是
lock(mySharedSyncObject)
的地方,可以非常轻松地意外不共享锁。完全避免它更容易,只需让我们承担应用锁定意图的责任即可。@ChrisSinclair您的回答给出了我想要的。谢谢。把
lock
想象成锁门。哪个门被锁上了?这是一个相关的问题,不是吗?是的,这显然是某种单一的参考点,但我只是感到困惑,为什么语言中的功能需要开发人员为作业实例化一个对象,而它可以是自动/内置的?所以我在想也许还有更多。@MuhammadA假设一个类中任何一个
lock
语句都会使用同一个对象来锁定。这是一个错误的假设。虽然这可能是最常见的操作,但锁定不同的对象(动态确定或静态确定)也是很常见的。这就是
lock
非常灵活的原因。例如,查看of,它为表的每个部分使用单独的lock对象。这允许同时访问字典(即使在删除和添加对象时),只要这些访问发生在表的不同部分。共享一个锁定对象意味着一次只能执行一个操作。