C# Lock语句-是否总是释放锁?
我最近读了一些文章,仍然有一些问题 在4.0实现中,如果在执行finally块中的Monitor.Exit(temp)之前发生线程中止或任何跨线程异常,会保留对象上的锁吗 是否有可能在此级别发生异常,使对象仍处于锁定状态?请阅读以下内容: 当引发此异常时,运行库在结束线程之前执行所有finally块 (这包括调用C# Lock语句-是否总是释放锁?,c#,.net,multithreading,C#,.net,Multithreading,我最近读了一些文章,仍然有一些问题 在4.0实现中,如果在执行finally块中的Monitor.Exit(temp)之前发生线程中止或任何跨线程异常,会保留对象上的锁吗 是否有可能在此级别发生异常,使对象仍处于锁定状态?请阅读以下内容: 当引发此异常时,运行库在结束线程之前执行所有finally块 (这包括调用Thread.Abort时当前正在执行的任何finally块) 所以是的,锁仍然会被释放。然而,这是否是一个非常不同的问题——尽管你不知道线程只是要释放锁——它可能在任何地方,并且可能处
Thread.Abort
时当前正在执行的任何finally
块)
所以是的,锁仍然会被释放。然而,这是否是一个非常不同的问题——尽管你不知道线程只是要释放锁——它可能在任何地方,并且可能处于改变锁保护状态的中间——因此,建议总是避免<代码>线程。
在4.0实现中,如果在执行finally块中的Monitor.Exit(temp)
之前发生线程中止或任何跨线程异常,是否会保持对对象的锁定
让我们看一下该代码,以便其他读者清楚:
bool lockWasTaken = false;
var temp = obj;
try
{
Monitor.Enter(temp, ref lockWasTaken);
{
body
}
}
finally
{
if (lockWasTaken)
{
// What if a thread abort happens right here?
Monitor.Exit(temp);
}
}
你的问题是不可回答的,因为它是基于一个错误的假设,即线程中止可能发生在最后一个块的中间。
线程中止不能发生在最后一个块的中间。这只是您永远不应该尝试中止线程的众多原因之一。整个线程可以在finally块中运行,因此不可中止
是否有可能在此级别发生异常,使对象仍处于锁定状态否。线程中止将被延迟,直到控件最终离开。解锁有效锁不会分配内存或引发其他异常。您可以自己尝试。使用
监视器。输入
将对象锁定在不同的线程上,调用Thread.Abort
并查看另一个线程是否可以在该对象上输入锁。Thread.Abort在CLR终止该线程之前将异常设置到堆栈上并最终执行块。Thread.Abort是否是唯一需要担心跨线程异常的情况?OutOfMemory或任何非托管异常可能使CLR进程保持运行,但仅在此时终止此线程?在这两种情况下,执行都会在某些状态发生变化时在未指定的点停止(如果不是的话,为什么要持有锁?)。这里唯一合理的选择是放弃,否则你只会弊大于利。你能看看我上面的评论吗?我知道这是一个相当模糊的问题,但我想了解所有可能的情况cases@Rod-OutOfMemory是一个很难推理的问题,因为如果finally块中的任何代码想要分配,那么很明显,这将失败。但是我认为lock
语句的解锁代码属于不太可能分配的代码集。我想不出任何解锁失败的情况,并且认为运行两周或在两台不同的机器上生成两个相同的GUI更有可能赢得彩票。释放有效锁不会失败,也不会分配内存。你的答案是正确的,但你可能要强调的关键推理是:如果finally块已经运行然后线程中止异常会被延迟到它完成为止。@EricLippert如果您要退出MemoryException,您会遇到更大的问题。想办法优雅地处理这件事是白费力气——改为治愈它,否则你总会看到副作用。