c# – 为什么这段代码不会以死锁结束

我有这个C#代码:

public class Locking
{

    private int Value1; private int Value2;

    private object lockValue = new Object();
    public int GetInt1(int value1, int value2)
    {
        lock (lockValue)
        {
            Value1 = value1;
            Value2 = value2;
            return GetResult();
        }

    }

    public int GetInt2(int value1, int value2)
    {
        lock (lockValue)
        {
            return GetInt1(value1, value2);
        }
    }

    private int GetResult()
    {
        return Value1 + Value2;
    }


}

所以基本上我期望一个死锁,如果我执行GetInt2但代码只是执行.任何好的解释.

解决方法:

这里的一般情况是同步对象是否可重入.换句话说,如果已经拥有锁,则可以通过相同的线程再次获取.另一种说法是对象是否具有“线程亲和力”.

在.NET中,Monitor类(实现lock语句),Mutex和ReaderWriterLock是可重入的. Semaphore和SemaphoreSlim类不是,您可以使用二进制信号量使代码死锁.实现锁定的最便宜的方法是使用Interlocked.CompareExchange(),它也不会重入.

使同步对象可重入需要额外的成本,它需要跟踪哪个线程拥有它以及在拥有线程上获取锁的频率.这需要存储Thread.ManagedId和一个计数器,两个整数.这影响了C中的选择,例如,C 11语言规范最终将线程添加到标准库. std :: mutex类在该语言中不可重入,并且拒绝添加递归版本的提议.他们考虑了使其重入过高的开销.也许有点笨手笨脚,花费在调试意外死锁上花费的时间相当微不足道的成本:)但它是一种语言,它不是灌篮,获得线程ID可以保证像它一样便宜.净.

这在ReaderWriterLockSlim类中公开,您可以选择.请注意RecursionPolicy属性,允许您在NoRecursion和SupportsRecursion之间进行选择. NoRecursion模式更便宜,而且非常纤薄.

上一篇:c# – 防止对象的并发访问


下一篇:C#-从字典获取资源时锁定资源