【问题标题】:How to know that a thread in a Thread Pool hangs/freezes如何知道线程池中的线程挂起/冻结
【发布时间】:2010-12-14 07:46:29
【问题描述】:

我有线程池的任务队列,每个任务都有冻结锁定它正在使用的所有资源的趋势。并且除非重新启动服务,否则这些无法释放。

ThreadPool 中有没有办法知道它的线程已经被冻结了?我有一个使用超时的想法,(虽然我仍然不知道怎么写),但我认为它不安全,因为处理的时间长度不统一。

【问题讨论】:

  • 一旦你知道一个线程被冻结了你打算怎么做?杀了它?这可能会使线程使用的数据结构处于不一致的状态。你最好找到死锁的根源并修复它。
  • 是的,我需要杀死它。它是一种“一劳永逸”的线程,所以我认为如果它被杀死不会造成任何伤害。
  • “我认为如果它被杀死没有伤害” - 著名的遗言......
  • 杀死线程是危险的并且是糟糕的做法(尤其是它们调用任何本机代码,这些代码通常包括 .NET API,其功能不仅仅是格式化文本;)。现在,使用它来调用 DebugBreak() 或类似的东西来调查死锁是一个好主意。

标签: c# multithreading threadpool


【解决方案1】:

我不想在这里太自以为是,但实际上找出问题所在并修复它是解决死锁的最佳方法。

  • 运行服务的调试版本并等待它死锁。它将保持死锁状态,因为这是死锁的一个很好的属性。
  • 将 Visual Studio 调试器附加到服务。
  • “打破一切”。
  • 打开线程窗口,开始探索...

除非您首先有合理的架构\设计\理由来选择受害者,否则不要这样做 - 时期。当线程处于某事的中间时,任意地在头上猛击线程几乎是灾难的秘诀。

【讨论】:

  • 这根本不是太冒昧。对“我的头在我切断后如何重新连接到我的身体上?”的正确回答?实际上是“一开始就不要切断它,鹅!” :-)
  • @paxdiablo 我不想概述任何类型的死锁检测算法,因为这将涉及某种线程安全性来实现,嗯,你知道的。用汽油灭火:)
【解决方案2】:

(这可能有点低级,但至少它是一个简单的解决方案。由于我不知道 C# 的 API,这是使用线程池的任何语言的通用解决方案。)

在每个用当前时间更新时间值的实际任务之后插入一个看门狗任务。如果这个值大于你的最大任务运行时间(比如 10 秒),你就知道有什么东西卡住了。

您可以在未来 10 秒内连续设置和重置一些计时器,而不是设置时间和轮询它。触发时,任务已挂起。

最好的方法可能是将每个任务包装在一个自动执行此操作的“看门狗”任务类中。这样一来,完成后,您将清除计时器,并且您还可以设置每个任务的超时,这可能很有用。

显然,线程池中的每个线程都需要一个时间/计时器对象,但这可以通过线程局部变量来解决。

请注意,此解决方案不需要您修改任务的代码。它只修改了将任务放入池中的代码。

【讨论】:

    【解决方案3】:

    一种方法是使用看门狗定时器(这种解决方案通常在硬件中完成,但也适用于软件)。

    让每个线程至少每五秒一次将线程特定的值设置为 1(例如)。

    然后你的看门狗定时器每十秒唤醒一次(同样,这只是一个示例图)并检查以确保所有值都是 1。如果它们不是 1,那么线程有被锁住了。

    然后看门狗定时器将它们全部设置为 0 并在下一个周期返回睡眠。

    如果您的工作线程以这样一种方式编写,以便它们能够在非冻结条件下及时设置值,则此方案可以正常工作。

    第一个锁定的线程不会将其值设置为 1,这将在下一个周期被看门狗定时器检测到。


    但是,更好的解决方案是首先找出线程冻结的原因并修复它。

    【讨论】:

      猜你喜欢
      • 2020-08-19
      • 1970-01-01
      • 1970-01-01
      • 2018-01-30
      • 2010-09-20
      • 1970-01-01
      • 1970-01-01
      • 2019-05-10
      相关资源
      最近更新 更多