在C#应用程序中检测死锁

25
可能重复:C#/.NET 分析工具以查找竞争条件/死锁 我正在调试一个应用程序,怀疑它被死锁并挂起。然而,这种情况只发生在几天之后,并且从未发生在我的电脑上,所以我无法将调试器连接到它。有没有任何实用工具或方法,可以查询运行中的应用程序,找出它所死锁的方法、锁定或任何其他问题?
更新:通常该应用程序在客户位置运行,我无法访问该机器,并且不太愿意要求他们安装大量软件。

你有源代码吗?https://dev59.com/r3E95IYBdhLWcg3wRL0t - David d C e Freitas
7个回答

25
你可以使用 WinDbg 来检查应用程序中的线程。以下是你可以执行的简要计划:
  • 当应用程序挂起时,将 WinDbg 文件复制到电脑上。
  • 要么将 WinDbg 附加到该进程,要么使用 ADPlus 获得进程的挂起转储文件。如果你选择使用 ADPlus,则需要在 WinDbg 中加载该转储文件。
  • 从 WinDbg 中加载 sos.dll,这样你就可以检查托管代码。
  • !threads 命令将显示应用程序中的所有线程,而 !clrstack 命令则会显示它们正在执行的内容。使用 ~e!clrstack 将所有线程的调用堆栈转储出来。查找调用 Wait 方法的情况,因为它们表示锁定。
  • !syncblk 命令将给出哪些线程持有不同的锁的信息。
  • 要查找给定线程尝试获取哪个锁,请切换到该线程并检查堆栈对象(!dso)。从这里,你应该能够找到该线程正在尝试获取的锁。

澄清:WinDbg 不需要常规安装。只需复制文件即可。另外,如果你采用了挂起转储文件,则可以在其他机器上继续调试(如果有需要)。

补充说明:Sosex 具有 !dlk 命令,可自动识别许多情况下的死锁。它并非总是有效,但当有效时,它可以为你完成所有工作,因此应该是你的首选。


!dlk 命令也值得一提...它可以为您查找死锁线程。 - Olivier
@icareo 很好的观点。然而,在某些情况下它不起作用,所以了解如何手动处理是很重要的。 - Brian Rasmussen

10

除了使用常规的lockMonitor.Enter锁定一些数据的方法,您还可以使用“TimedLock”结构。

如果无法及时获取锁定,此TimedLock将抛出异常,并且如果您有未释放的某些锁定,它还可以向您发出警告。

这篇文章由Ian Griffiths撰写,可能会对您有所帮助。


我先试一下这个,然后添加大量日志来尝试跟踪失败的锁定。谢谢! - Jon Tackabury
1
TimedLock 存在潜在问题,正如这篇文章所示: http://blogs.microsoft.co.il/blogs/sasha/archive/2009/01/27/why-concurrency-is-hard-or-timedlock-can-get-you-in-trouble.aspx - Tomer Pintel

7

在并发编程中使用超时是一个可怕的想法。这会导致不确定性,因此无法重现行为。尝试使用死锁检测工具,如CHESS。更好的方法是使用无锁算法来最小化使用的锁的数量,或者完全避免使用锁,并将程序分区成单线程隔间,并使用队列在隔间之间传递数据(更常被称为消息传递/actor并发)。


1

同样适用于Windows 10。 - Jimmy

1

你们那里实际上有一个非常有趣的问题。有几件事情可以做:

使用好的日志记录器:复现多线程错误的一种方法是使用会打印执行操作和执行它们的线程的日志记录器,这样您就可以找到指引您找到错误的跟踪。如果您可以添加日志记录器,这是一个相当简单的解决方案。

使用FSP:使用FSP定义您的多线程系统。这样,您将能够创建一个过程的有限状态机,通过它来查找错误。这个解决方案是一个更数学化的解决方案。

我给你的两个解决方案/程序,实际上是英国大学和美国大学在处理多线程开发时的主要差异。在英国,教授们更愿意尝试使用FSP证明他们的系统没有错误,然后再进行编程,而美国人则更喜欢测试以证明它们的正确性,这是一种口味问题。

我真的建议阅读这本书:Jeff Magee和Jeff Kramer:并发:状态模型和Java程序,Wiley,1999年


0

这是一个非常有趣的问题,但也很痛苦,因为它只会在几天后才发生。我在CodeProject上找到了这篇文章,这可能对你有所帮助。

一种老派的方法是记录大量消息并使用日志文件来尝试检测它何时发生。 :)


0
除了这里的答案之外,通常情况下,你会发现在线程编程中非常有用的一件事是确保你的开发机器是一个多处理器的机器,特别是死锁问题,通常更容易被可靠地重现。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接