您是不是应该请求 .NET 中的锁定超时?
Posted
技术标签:
【中文标题】您是不是应该请求 .NET 中的锁定超时?【英文标题】:Should you request timeouts on locks in .NET?您是否应该请求 .NET 中的锁定超时? 【发布时间】:2010-10-04 13:26:42 【问题描述】:在Release It! 中,Michael Nygard 解释说,许多灾难性系统故障通常是由一连串的错误引起的。例如,两个线程死锁。现在线程池中的线程减少了两个,因此其他线程上的负载增加,从而增加了它们死锁的可能性。突然,服务器根本没有响应,因为线程池耗尽,这导致负载均衡器将流量转移到其他服务器(它们都运行相同的代码),这增加了它们的可能性的死锁。突然整个农场都离线了。
大多数 RDBMS 服务器检测死锁并决定“失败者”(一个事务被中止,另一个可以继续)。相比之下,在 C# 中,lock 语句将无限期地等待获得锁。
但是,您可以调用 Monitor.TryEnter(lockObject, TimeSpan) 来请求锁定或超时。如果超时到期并且无法获取锁,则返回 false。有些有wrapped this in using statements 以保持良好的语法。
所以我的问题是,您是否总是使用超时来获取锁?与死锁场景相比,超时会产生哪些问题?
【问题讨论】:
【参考方案1】:我通常会使用超时。这里最大的问题是,如果达到超时,请求操作将被中止。这显然比死锁更可取。但是那里有一个更大的问题:如果操作很关键并且您因为其他事情陷入僵局而开始中止,如果您的设计不合理,您最终可能会导致您通过这种方法描述的农场下降问题(虽然更软:您的应用将不再工作,但您并没有失去控制)。
主要区别在于您实际上在这里拥有控制权,而如果线程开始死锁,那么一旦故障开始,您就无法在代码中解决问题。
【讨论】:
【参考方案2】:作为一般规则,我从不创建具有无限超时的锁。它只会导致难以发现和难以调试的死锁。添加超时检查不需要任何额外的工作,即使它只是抛出异常,并且如果您遇到死锁,它几乎会立即通知您。更重要的是,它可以帮助您找到可能不会导致完全死锁的 bu 锁导致的瓶颈。
【讨论】:
【参考方案3】:可以证明死锁不会发生。也可以在运行时证明即使不依赖于竞争条件也可能发生死锁(例如,参见 Linux 的 lockdep)。
因此,总是尝试锁定是没有意义的。视情况而定。
【讨论】:
【参考方案4】:您能否从锁定尝试超时的情况中优雅地恢复?如果可以,那么一定要使用超时。如果你不能,那么超时就没有什么意义了。当你恢复执行时你会做什么?充其量您可以退出并显示错误消息。超时有其用途,但它们也可以用来隐藏微妙的线程错误,所以我认为最好的建议是谨慎使用。
【讨论】:
我想问题变成了,如果你能做的就是显示一条错误消息,那比无限期地等待更好吗?死锁不会给您回滚的机会,并且错误可能是比冻结的应用程序(稍微)更好的用户体验。以上是关于您是不是应该请求 .NET 中的锁定超时?的主要内容,如果未能解决你的问题,请参考以下文章