锁定语句 - 是否始终释放锁定?

时间:2013-10-07 13:14:18

标签: c# .net multithreading

我最近阅读了this post from Eric Lippert regarding the lock implementation in c#,但仍然存在一些问题。

在4.0实现中,如果在执行finally块中的Monitor.Exit(temp)之前发生了线程中止或任何交叉线程异常 - 是否会锁定对象?

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

2 个答案:

答案 0 :(得分:14)

  

在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块中运行,因此不可中止。

  

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

没有。线程中止将被延迟,直到控制离开最终。解锁有效锁不会分配内存或抛出另一个异常。

答案 1 :(得分:9)

了解ThreadAbortException

  

当引发此异常时,运行时会在结束线程之前执行所有 finally

(这包括在调用finally当前执行的任何Thread.Abort

所以是的,锁将会被释放。这是否可取是一个非常不同的问题 - 你不知道线程即将释放锁 - 它可能在任何地方,并且可能正在改变锁保护的状态 - 一如既往,建议是避免Thread.Abort