为什么我们需要在C#中锁定对象?

5

我从未真正理解过这一点。它看起来几乎像是创建一个虚拟对象并将其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;  
        }  
    }  
}  

来自https://msdn.microsoft.com/en-us/library/c5kehkcz.aspx

为什么语言设计者不能使它这样呢?

在IT技术方面,无法提供更多上下文信息。

class Account  
{  
    decimal balance;   

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

会等同吗?

5
完全不需要,否则没人会知道如何使用“lock”。需要将参数传递给“lock”语句的原因非常明确,如果作者不理解这些原因,那么这个问题就非常重要。 - rucamzu
@rucamzu - 我想我误读了问题。 - Sayse
2个回答

7
lock所传入的实例用于标识关键区域
您的代码中可能有许多无关的关键区域,每个关键区域将锁定不同的对象。一个无参数的lock语句(如您所建议的)无法区分许多关键区域。 编辑说明: 尽管这似乎很明显,但值得注意的是,需要进入给定关键部分的每个单独部分都必须可以访问已锁定的对象。因此,这不是在lock语句之前和在同一范围内创建任意实例的问题。

是的,你说得对,我看错了,我认为他不理解锁在做什么。感谢评论。 - mybirthname
@mybirthname 没问题。仅供记录,我认为你的解释清晰且有用。 - rucamzu

1
我认为混淆在于lock关键字的作用。它并不是说只有1个线程可以进入该代码部分,而是在说两件事情:
  1. 只有一个拥有thisLock的线程可以进入此代码部分
  2. 任何其他使用thisLock锁定的部分也不允许除该线程以外的任何线程进入,因为该线程拥有thisLock。
你所提出的建议只会实现第一个,但不包括第二个。看看这个例子:
class Account
{
    decimal balance;
    private Object thisLock = new Object();
    private Object thisLock2 = new Object();

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

        // more code here but no locking necessary...

        lock(thisLock)
        {
            // only one thread can enter here who has thisLock
        }

        lock (thisLock2)
        {
            // If T1 (thread1) is working with thisLock, T2 can come here since it has nothing to do
            // with thisLock.
        }
    }

    public void AnotherOperation()
    {
        lock (thisLock)
        {
            // code here...
        }
    }

    public void YetAnotherOperation()
    {
        lock (thisLock)
        {
            // code here...
        }
    }
}

当一个线程,比如T1,正在使用第一个锁进行取款操作时,所有其他使用lock(thisLock)的类部分也不允许其他线程进入。然而,使用thisLock2的部分可以被其他线程进入。
最好的理解lock关键字的方法,至少在我学习时有帮助的,是将其视为人质。换句话说,在执行某些代码时,需要在你的示例中采取人质(thisLock)。因此,一旦采取了该人质,直到该线程释放人质,没有其他线程可以采取它作为人质。因此,所有其他需要相同人质的代码部分都变得不可用。

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