C# Lock语句-是否总是释放锁?

C# Lock语句-是否总是释放锁?,c#,.net,multithreading,C#,.net,Multithreading,我最近读了一些文章,仍然有一些问题 在4.0实现中,如果在执行finally块中的Monitor.Exit(temp)之前发生线程中止或任何跨线程异常,会保留对象上的锁吗 是否有可能在此级别发生异常,使对象仍处于锁定状态?请阅读以下内容: 当引发此异常时,运行库在结束线程之前执行所有finally块 (这包括调用Thread.Abort时当前正在执行的任何finally块) 所以是的,锁仍然会被释放。然而,这是否是一个非常不同的问题——尽管你不知道线程只是要释放锁——它可能在任何地方,并且可能处

我最近读了一些文章,仍然有一些问题

在4.0实现中,如果在执行finally块中的Monitor.Exit(temp)之前发生线程中止或任何跨线程异常,会保留对象上的锁吗

是否有可能在此级别发生异常,使对象仍处于锁定状态?

请阅读以下内容:

当引发此异常时,运行库在结束线程之前执行所有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,您会遇到更大的问题。想办法优雅地处理这件事是白费力气——改为治愈它,否则你总会看到副作用。