锁内锁

rei*_*als 61 c# locking

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

lock(sync)
{
  // something
  lock(sync)
  {
    //something
    lock(sync)
    {
      //something
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

我运行这段代码,看起来很好,但在某些情况下可能会抛出错误?

ta.*_*.is 47

lock是一个包装的Monitor.EnterMonitor.Exit:

lock关键字要求Enter在该块的开始和Exit在块的结尾.从前者的文件:

从以下文档Monitor.Enter:

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

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

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

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

  • 真的不值得注意,因为持有锁的方法通常也会调用获取锁的方法.在某些设计中,第二个锁会死锁...我已经在这样的系统上工作了,程序必须保持自己的引用计数,并且只在最外层获取和释放锁. (12认同)
  • 值得注意的是,内部的"锁定"本质上是多余的:你已经*拥有锁定; 再次要求它永远不会失败. (2认同)

Thy*_*ine 16

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

旁白:这个答案有关于锁实际如何工作的更好的细节

锁定发生在该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);
    }
}
Run Code Online (Sandbox Code Playgroud)