内锁内锁

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

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

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

15131 次浏览

lockMonitor.EnterMonitor.Exit的包装器:

lock关键字在块的开始调用 Enter,在块的结束调用 Exit。来自前者的文件:

来自 Monitor.Enter 的文档:

同一个线程可以不止一次地调用 Enter而不被阻塞,这是合法的; 但是,在其他等待对象的线程解除阻塞之前,必须调用相同数量的 Exit调用。

因为对 EnterExit的调用是成对的,所以代码模式具有良好定义的行为。

但是,请注意,lock不一定是无异常的构造:

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

根据 MSDN (参见 给你给你) ,这是定义良好的行为,不会引起任何问题。

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

旁白: 这个答案有更多关于锁实际工作原理的详细信息

锁发生在 Thread级别,因此在同一个线程上第二次调用它将是多余的。我认为它不会有任何性能损失(尽管这取决于。网络已经写好了,所以我不能保证)

很多时候,您有一个公共函数,它调用类中的另一个公共函数,当分别使用时,这两个函数都需要锁。如果不允许这样做,下列措施将会失败:

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);
}
}