3

关于 .net 中 Lock() 构造的两个问题

首先,我知道如果一个对象被锁定在一个类中,而另一个类试图锁定同一个对象,则会产生死锁。但为什么?我在 MSDN 上读过它,但 MSDN 很少那么清楚。

----编辑问题一---- 仍然很困惑。我有一个产生许多 Threadpool 线程的主线程(UI 线程)。每个子线程在使用数据之前都会锁定数据。这每次都很好。

如果我然后尝试从 UI 线程锁定相同的数据以检查我是否应该为边缘情况创建一个新线程,我几乎每次都会创建死锁。

----编辑问题二---- 其次,如果我有一个我锁定的复合对象,那么其中的所有子对象是否也被锁定?短代码演示:

internal sealed class Update
{
    //Three objects instantiated via other external assemblies
    public DataObject One { get; set; }
    public DataObject Two { get; set; }
    public ReplayStatus Status { get; set; }
}

如果我调用 lock(UpdateObject) 三个内部对象中的每一个以及所有子对象都被锁定了吗?

所以我应该做这样的事情来防止线程玩我的数据对象:

Lock(UpdateObject.One)
{
    Lock(UpdateObject.Two)
    {
        Lock(UpdateObject.Status)
        {
            //Do Stuff
        }
    }
} 
4

2 回答 2

5

首先,我知道如果一个对象被锁定在一个类中,而另一个类试图锁定同一个对象,则会产生死锁。

不可以。如果一个线程锁定了一个对象,而另一个线程尝试锁定该对象,则第二个线程必须等待第一个线程退出锁定。

死锁是另外一回事:

1. thread1 locks instanceA
2. thread2 locks instanceB
3. thread1 attempts to lock instanceB and now must wait on thread2
4. thread2 attempts to lock instanceA and now must wait on thread1

这两个线程不能再执行,因此永远不会释放它们的锁。真是一团糟。

如果我调用 lock(UpdateObject) 三个内部对象中的每一个以及所有子对象都被锁定了吗?

不,“锁定”仅在锁定的实例上。注意:锁不会阻止除第二个线程之外的任何东西同时获取该实例上的锁。

于 2012-04-26T01:56:18.680 回答
3

首先,锁的全部意义在于两段代码不能同时获得同一个锁。这是为了协调多个线程使用相同的东西而不相互干扰。如果您在一个对象上有一个锁,那么任何其他试图获得锁的人都会阻塞(等待)直到原始锁被释放(在任何给定时间只有一个线程可以拥有锁)。如果第一个线程从不放弃锁,或者如果两个线程都在等待对方的某些东西并且在每个线程都得到它正在等待的东西之前都无法继续,那么你只会遇到死锁。

其次,如果您lock是 C# 中的一个对象,那么您实际上并没有在任何语义上“锁定”该对象。您正在获取对象上的“锁定”(稍后您将 releaserelenquish)。该对象纯粹是一个方便的令牌,用于唯一标识您希望获得的锁。所以不,对象上的锁不会在该对象的任何子部分上创建锁。

于 2012-04-26T01:56:47.993 回答