锁内锁

时间:2012-02-07 08:16:26

标签: c# locking

我想知道这种结构是否会导致错误:

lock(sync)
{
  // something
  lock(sync)
  {
    //something
    lock(sync)
    {
      //something
    }
  }
}

我已运行此代码,看起来很好,但在某些情况下可能会引发错误?

3 个答案:

答案 0 :(得分:46)

lock is a wrapper for Monitor.Enter and Monitor.Exit

  

lock关键字在块的开头调用Enter,在块的末尾调用Exit。从前者的文件:

From the documentation for Monitor.Enter

  

同一个线程在没有阻塞的情况下不止一次调用Enter是合法的;但是,在等待对象的其他线程将解除阻塞之前,必须调用相同数量的Exit调用。

由于对EnterExit的调用已配对,因此您的代码模式具有明确定义的行为。

但请注意,lock不能保证是无异常的构造:

  

如果ThreadInterruptedException中断正在等待输入Interrupt语句的线程,则抛出lock

答案 1 :(得分:16)

解释为什么它是明确定义的行为,永远不会失败:

除此之外:This answer has better details about how locks actually work

锁定发生在Thread级别,因此在同一个线程上再次调用它将是多余的。我认为它不会有任何性能损失(尽管这将取决于.Net的内部是如何编写的,因此我无法保证)

很多时候,你有一个公共函数可以调用你班级中的另一个公共函数,这些函数在单独使用时都需要锁定。如果不允许,则以下内容将失败:

private Dictionary<string, int> database = new Dictionary<string, int>();
private object databaseLock = new object();
public void AddOrUpdate(string item)
{
    lock (databaseLock)
    {
        if (Exists(item))
            database.Add(item, 1);
        else
            ++database[item];
    }
}
public bool Exists(string item)
{
    lock (databaseLock)
    {
        //... Maybe some pre-processing of the key or item...
        return database.ContainsKey(item);
    }
}

答案 2 :(得分:0)

根据MSDN(请参阅herehere),这是明确定义的行为并且没有问题。