13

说,如果我在 C# 代码上有以下块:

public class SynchedClass
{
    public void addData(object v)
    {
        lock(lockObject)
        {
            //Shall I worry about catching an exception here?

            //Do the work
            //arr.Add(v);
        }
    }
    private List<object> arr = new List<object>();
    private object lockObject = new object();
}

我应该尝试在lock块内捕获异常吗?(我主要担心的是锁内可能会引发异常,这将阻止锁被“解锁”。)

4

3 回答 3

28

当异常从锁块中逃逸时,锁将被释放。

那是因为lock(){...}被编译器大致翻译成:

Monitor.Enter(obj);
try{

 // contents of the lock block

}finally{
    Monitor.Exit(obj);
}
于 2013-04-07T09:05:59.650 回答
3

除了释放互斥体之外,还有更多需要考虑的事情。

a中发生异常lock会释放锁,但程序现在处于什么状态?等待锁的线程现在将被唤醒,并且现在可能正在处理无效状态。这是一个没有理想解决方案的难题。

最好的办法是尽量保持你的锁尽可能小,并调用不会抛出的方法。(那是忽略房间里的大象是邪恶的ThreadAbortException......)

有关这些问题的详细讨论,请参阅 Eric Lippert 的文章:Locks and exceptions do not mix

于 2013-04-07T09:32:30.763 回答
2

“lock (x) ...”形式的 lock 语句,其中 x 是引用类型的表达式,完全等同于 (C# 4.0):

 bool entered = false;
 try { 
    System.Threading.Monitor.Enter(x, ref entered);
  ... 
 }
 finally { if (entered) System.Threading.Monitor.Exit(x); }
于 2013-04-07T09:07:17.600 回答