如何在多线程c#程序中找到死锁的原因?

时间:2010-03-07 20:16:05

标签: c# multithreading

基本上我有一个c#服务器程序(不在IIS中的控制台应用程序)偶尔会进入死锁状态。

有一件事很奇怪,当我连接调试器时,我看到3个线程正在等待一个锁,但锁内没有线程(使用visual studio中的线程窗口)!这里发生了什么......我猜视觉工作室调试器正在撒谎。

但无论如何......我应该使用哪些技术或工具?

由于

5 个答案:

答案 0 :(得分:6)

每次线程即将进入/离开关键部分以及每次成功获取锁定时,我都会开始发送跟踪输出。使用System.Diagnostics.Trace类。

然后,您应该能够从跟踪输出中确定哪个线程实际上具有锁定。

典型的跟踪代码:

Trace.WriteLine("Acquiring lock - foo");
lock (foo)
{
    Trace.WriteLine("Acquired lock - foo");
    // Do some stuff
    Trace.WriteLine("Releasing lock - foo");
}
Trace.WriteLine("Released lock - foo");

根据程序结构的方式,除非在跟踪输出中包含线程信息,否则这可能没有用,例如:

Trace.WriteLine(string.Format("Thread {0} - Acquiring lock - foo",
    Thread.CurrentThread.ManagedThreadId));

一旦你弄清楚哪个线程锁定,你就可以进入调试器,看看它等待哪个锁,然后使用相同的跟踪输出找出谁拥有其他锁定。在大多数情况下,将有两个线程参与死锁,这将让你找到它们。

答案 1 :(得分:2)

始终有WinDbg,但学习曲线可能有点令人生畏。

但请参阅Brians关于这个问题的优秀答案:Detecting deadlocks in a C# application

答案 2 :(得分:1)

您还可以将WinDbg与SOS.dll一起使用,以找出死锁所在的位置。看看this文章。有问题的SOS.dll命令是!syncblk - 它扫描.NET线程以查找有关潜在死锁的信息。

答案 3 :(得分:0)

您的线程可能存在竞争条件。你的一个线程没有放弃锁定,它没有使用它或允许其他人使用它。当线程有锁并在放弃之前被杀死时也会发生这种情况。您可能想查看任何针对死锁的编程解决方案,例如Sleeping Barber,Lamport's Bakery,Dekker算法,Peterson算法或Dining Philosophers。

我不知道你是如何管理线程的,所以我不能告诉你哪种算法是正确的解决方案,但它们是操作系统内部最常见的并发和死锁管理解决方案,所以他们应该处理你的问题。

答案 4 :(得分:0)

总之,Chess是微软的一个程序,用于帮助解决这些问题。

从他们的网站:

  

CHESS反复运行并发   测试确保每次运行都需要   不同的交错。如果   交错导致错误,   CHESS可以重现交错   用于改进调试。 CHESS是   可用于托管和本机   程序