【问题标题】: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 以保持良好的语法。

所以我的问题是,您是否总是使用超时来获取锁?与死锁场景相比,超时会产生哪些问题?

【问题讨论】:

    标签: .net multithreading scalability


    【解决方案1】:

    我通常会使用超时。这里最大的问题是,如果达到超时,请求操作将被中止。这显然比死锁更可取。但是那里有一个更大的问题:如果操作很关键并且您因为其他事情陷入僵局而开始中止,如果您的设计不合理,您最终可能会导致您通过这种方法描述的农场下降问题(虽然更软:您的应用将不再工作,但您并没有失去控制)。

    主要区别在于您实际上在这里拥有控制权,而如果线程开始死锁,那么一旦故障开始,您就无法在代码中解决问题。

    【讨论】:

      【解决方案2】:

      作为一般规则,我从不创建具有无限超时的锁。它只会导致难以发现和难以调试的死锁。添加超时检查不需要任何额外的工作,即使它只是抛出异常,并且如果您遇到死锁,它几乎会立即通知您。更重要的是,它可以帮助您找到可能不会导致完全死锁的 bu 锁导致的瓶颈。

      【讨论】:

        【解决方案3】:

        可以证明死锁不会发生。也可以在运行时证明即使不依赖于竞争条件也可能发生死锁(例如,参见 Linux 的 lockdep)。

        因此,总是尝试锁定是没有意义的。视情况而定。

        【讨论】:

          【解决方案4】:

          您能否从锁定尝试超时的情况中优雅地恢复?如果可以,那么一定要使用超时。如果你不能,那么超时就没有什么意义了。当你恢复执行时你会做什么?充其量您可以退出并显示错误消息。超时有其用途,但它们也可以用来隐藏微妙的线程错误,所以我认为最好的建议是谨慎使用。

          【讨论】:

          • 我想问题变成了,如果你能做的就是显示一条错误消息,那比无限期地等待更好吗?死锁不会给您回滚的机会,并且错误可能是比冻结的应用程序(稍微)更好的用户体验。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-08-03
          • 1970-01-01
          • 2017-10-20
          • 2021-09-23
          • 1970-01-01
          相关资源
          最近更新 更多