锁块内的异常
本文关键字:异常 | 更新日期: 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); }