Sas*_*sha 7 .net c# multithreading readerwriterlockslim
MSDN文档和许多使用ReaderWriterLockSlim类的示例建议使用以下模式:
cacheLock.EnterWriteLock();
try
{
//Do something
}
finally
{
cacheLock.ExitWriteLock();
}
Run Code Online (Sandbox Code Playgroud)
但我很好奇它是否完全安全.获取锁之后是否可能发生某些异常,但是在try语句之前锁定被锁定状态?最明显的候选人是ThreadAbortException.我知道这种情况的可能性非常小,但后果极其糟糕 - 所以我认为值得考虑一下.我不相信编译器理解这种模式并阻止处理器在try语句之前中断线程.
如果理论上有可能这个代码不安全,有没有办法让它更安全?
小智 8
理论上只有三种方法可以让我想到:
ThreadAbortException你已经提到了.这很容易正确处理:只是确保你永远不会打电话Thread.Abort().你几乎肯定不需要; 几乎总有更好的方法来达到预期的效果.
只有当你真的,真的,真的需要调用它,并且你正在中止线程是一个与保持锁打开的风险,放置的代码的整个块(从Enter到Exit)在try... finallywhere子句中的try-block是空的.只会在当前处理程序完成时Thread.Abort()抛出.ThreadAbortExceptionfinally
StackOverflowException是另一种可能性.它可能发生在通话期间ExitWriteLock.这也很容易:当发生堆栈溢出时,进程终止.你不能抓住或处理这个.由于进程终止,进程中的其他任何线程都不会保持任何锁定.
OutOfMemoryException理论上可能会在电话会议期间被抛出ExitWriteLock.不同的是StackOverflowException,这个理论上是可捕捉的.如果你没有捕获它,那么进程将再次终止,并且进程中的其他任何线程都不会保持任何锁定.但是,如果你确实抓住了它,你就不能指望正确处理它,并且很可能,你的其他线程很快就会开始抛出这个异常.
简而言之,我不担心.
它可能是一个问题,显然是在一些高负荷情况下.此文章进入它进一步,但它基本上可以归结为使用再加上最后一个空try块来获取和释放锁:
var lockIsHeld = false;
try {
try {
}
finally {
rwl.EnterReadLock();
lockIsHeld = true;
}
// Do work here
}
finally {
if (lockIsHeld) {
rwl.ExitReadLock();
}
}
Run Code Online (Sandbox Code Playgroud)
这种方法可以保证您的锁始终被获取和释放,因为即使在a的情况下,也可以保证运行ThreadAbortException.
其他例外情况在@ hvd的帖子中有详细说明.
我个人不会担心,除非你真的在野外看到这个问题...