我想检查以下代码是否抵抗ThreadAbortException并且不会导致孤立锁定。如果不是,那么避免孤儿锁定的最佳模式是什么?
ReaderWriterLockSlim _lock = new ReaderWriterLockSlim();
public void DoStaff()
{
_lock.EnterWriteLock();
//Is this place where ThreadAbotException can corrupt my code, or is there JIT optimalization which prevent this from happening???
try
{
...
}
finally
{
_lock.ExitWriteLock();
}
}
根据以下链接http://chabster.blogspot.cz/2013/07/a-story-of-orphaned-readerwriterlockslim.html,有(或至少有)可能的方法如何创建孤立锁,但我运行示例代码一段时间没有任何运气。
我使用的是.NET 4.0
Debug和Release中的行为有什么区别吗?
答案 0 :(得分:4)
是的,ThreadAbortException
可能会在那里发生,在这种情况下,try
将不会被输入,因此您永远不会退出写锁定。
这个问题没有很好的通用解决方案。这就是为什么Eric Lippert(以及其他人)说Locks and exceptions do not mix。
您具体询问ThreadAbortException
,这让我相信您正在考虑在您的应用中使用Thread.Abort
进行某种线程控制。我劝你重新考虑一下。如果您希望能够取消线程,则应使用Cancellation或类似的东西。在最严峻的情况下使用Thread.Abort
是一个可怕的坏主意。它当然不应该是你的程序整体设计的一部分。
答案 1 :(得分:1)
为了使面向线程中止时使用锁定原语的代码具有健壮性,每个锁定获取和锁定释放请求都必须通过或者通过非共享令牌执行,该令牌可以给予& #34;所有权"锁。根据锁定API的设计,令牌可以是某种特定类型的对象,任意Object
或作为ref
参数传递的变量。但是,在获取锁之前,通过某种方式创建和存储令牌是必要的,这样如果令牌被创建但存储失败,则可以放弃令牌而不用困难。不幸的是,尽管监视器锁已经添加了(在.NET 4.0中)使用Monitor.Enter
作为令牌的Monitor.TryEnter
和ref bool
的重载,但我知道没有读写器锁的等价物。
如果想要一个中止安全的读写器锁定功能,我建议你需要一个围绕它设计的类;它应该跟踪哪些线程持有读取器或写入器访问权限,而不是依赖线程来释放锁,它应该在等待释放锁时,确保持有它的线程仍然存活。如果线程在保持读访问权限时死亡,则应该释放它。如果线程在持有正确访问权限时死亡,则任何未决或将来尝试获取锁定都应立即引发异常。
否则,有一些技巧可以保护代码块免受Thread.Abort()
的影响。遗憾的是,我不知道任何干净的方法来围绕锁定获取请求包围代码,以便Abort
在请求本身可以干净地中止而不成功但将被延迟时将起作用如果请求成功。
通过这种方法,框架可以安全地允许无限循环中的线程被另一个线程杀死,但设计可以安全使用的机制需要比放入Thread.Abort()
更多的努力。