.net锁 - 两个问题

时间:2012-04-26 01:49:08

标签: c# .net multithreading

关于.net

中的Lock()构造的两个问题

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

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

如果我然后尝试从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
        }
    }
} 

2 个答案:

答案 0 :(得分: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)是三个内部对象中的每一个,并且所有子对象都被锁定了吗?

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

答案 1 :(得分:3)

首先,锁的整个要点是两段代码不能同时获得同一个锁。这是为了协调多个线程使用相同的东西而不会相互干扰。如果你对一个对象有一个锁,那么试图获得锁的其他任何人都会阻塞(等待)直到释放原始锁(在任何给定时间只有一个线程可以拥有锁)。如果第一个线程永远不会放弃锁定,或者两个线程都在等待彼此之间的某些事情,并且在每个线程都得到它正在等待的内容之前都不能继续,那么你只有一个死锁。

其次,如果你在C#中使用lock一个对象,那么你就不会在任何语义意义上“锁定”该对象。您在对象上获取“锁定”(您稍后发布 relenquish )。该对象纯粹是一个方便的标记,用于唯一标识您希望获取的锁。所以不,对象的锁定不会在该对象的任何子部分上创建锁定。