说,如果我在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
块内的异常吗? (我主要担心的是,锁内部可能会引发异常,这会阻止锁被“解锁”。)
答案 0 :(得分:21)
当异常从锁定块中逃脱时,将释放锁定。
这是因为lock(){...}
大致由编译器翻译成:
Monitor.Enter(obj);
try{
// contents of the lock block
}finally{
Monitor.Exit(obj);
}
答案 1 :(得分:2)
形式为“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); }
答案 2 :(得分:2)
除了发布互斥锁之外,还有更多要考虑的因素。
使用lock
发生的异常将释放锁定,但现在该程序处于什么状态?等待锁的线程现在将被唤醒,现在可能正在处理无效状态。这是一个难以解决的问题。
最好的办法是尽量让你的锁尽可能小,并调用不抛出的方法。 (这忽略了房间里的elepant是邪恶的ThreadAbortException
...)
有关这些问题的详细讨论,请参阅Eric Lippert的文章:Locks and exceptions do not mix。