锁块内的异常

本文关键字:异常 | 更新日期: 2023-09-27 18:08:06

比如说,如果我有下面的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块中的异常吗?(我主要担心的是,异常可能会在锁内部引发,这将阻止锁被"解锁"。)

锁块内的异常

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

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

Monitor.Enter(obj);
try{
 // contents of the lock block
}finally{
    Monitor.Exit(obj);
}

要考虑的不仅仅是释放互斥锁。

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

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

有关这些问题的详细讨论,请参阅Eric Lippert的文章:锁和异常不能混合。

形式为"lock (x)…"的锁语句,其中x是引用类型的表达式,精确地等效于(c# 4.0):

 bool entered = false;
 try { 
    System.Threading.Monitor.Enter(x, ref entered);
  ... 
 }
 finally { if (entered) System.Threading.Monitor.Exit(x); }