基本上我有一个c#服务器程序(不在IIS中的控制台应用程序)偶尔会进入死锁状态。
有一件事很奇怪,当我连接调试器时,我看到3个线程正在等待一个锁,但锁内没有线程(使用visual studio中的线程窗口)!这里发生了什么......我猜视觉工作室调试器正在撒谎。
但无论如何......我应该使用哪些技术或工具?
由于
答案 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是 可用于托管和本机 程序