我最近阅读了Eric Lippert关于C#中锁实现的这篇文章,但依然有一些问题待解决。
在4.0实现中,如果在finally块中执行Monitor.Exit(temp)之前发生线程中止或任何跨线程异常,那么对象上的锁是否会保持?
在这个级别上是否有可能发生异常,导致对象仍处于锁定状态?
在4.0实现中,如果在finally块中执行Monitor.Exit(temp)之前发生线程中止或任何跨线程异常,那么对象上的锁是否会保持?
在这个级别上是否有可能发生异常,导致对象仍处于锁定状态?
在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 块的中间,因此您的问题无法获得答案。
线程中止不可能发生在 finally 块的中间。这只是许多原因中的一个,说明为什么您永远不应该尝试中止线程。整个线程可能正在运行 finally 块,因此不能被中止。
在此级别是否有可能发生异常,使对象仍处于锁定状态?
不会。线程中止将延迟到控制离开 finally。解锁有效锁并不会分配内存或引发其他异常。
了解关于 ThreadAbortException
的相关信息:
当此异常被触发时,运行时会在结束线程之前执行所有的finally块。
(这包括在调用Thread.Abort
时正在当前执行的任何finally
块)
是的,锁仍然会被释放。不过,这是否值得提倡是一个非常不同的问题 - 您并不知道线程即将释放锁 - 它可以在任何地方,并且可能在变异锁保护的状态的中间阶段 - 因此,一如既往的建议是避免使用Thread.Abort
。
lock
语句的unlock代码应该属于不太可能分配内存的代码集合。我想不出任何情况下解锁会失败,而且认为赢得两周的彩票或在两台独立的计算机上生成两个相同的GUID要更有可能。 - Damien_The_Unbeliever
Monitor.Enter
在另一个线程上锁定一个对象,调用Thread.Abort
并查看是否可以让另一个线程进入该对象的锁定状态。 - vcsjones