2011-08-28 107 views
1

面对应用程序挂起时出现的间歇性多线程错误。当我暂停调试时,我看到该线程在锁(_sync)子句上等待。所以问题是:线程锁无限等待

  1. 当某些其他线程锁定对象时,是否等待锁定的唯一原因是?
  2. 如何知道什么线程持有特定对象的锁(在调试或运行时)?

我相信这不是一个“死锁”,因为死锁意味着存在至少两个对象和两个线程,而在考虑代码时只有一个同步对象。我认为一些其他线程锁定了对象并挂起,但我无法找到它是哪个线程。

+0

如果你的应用程序挂起0%的CPU,那么你的死锁问题> 0.999。如果它与100%的CPU挂起,那么你有没有终止繁忙循环。 –

+0

嗯,不一定。例如,如果应用程序挂起0%CPU,则持有该锁的线程可能仅在I/O上被阻塞。唯一可以肯定的是,100%的CPU可能意味着无限循环。 0%的CPU可以有很多不涉及死锁的解释。 – cdhowie

+0

@cdhowie我假设最终IO将完成。 –

回答

0

调试此方法的一种方法(没有闪亮的VS2010提示)只能通过属性/存取器访问_sync。在那里放置了一些诊断文本或断点,你可以看到什么线程想要同步和什么时候。

除此之外,我不能给出任何合理的答案,没有看到代码。

4

我将记录一些重要的调试技术。从Debug + Windows + Threads开始,它会显示您的进程中正在运行的所有线程的列表。您可以将鼠标悬停在“位置”列上,您将看到一个工具提示,显示该线程的堆栈跟踪。这可以让你快速地回到实际运行代码的线程中。双击其中一个感兴趣的部分,然后切换到Debug + Windows + Call Stack以获得更持久的视图。这可能会帮助您找到获取该锁的线程。

如果失败,你可以找出哪个线程拥有锁定对象。通过双击切换到阻止的线程,然后使用Debug + Windows + Memory + Memory 1.在地址框中键入“_sync”。右键单击窗口并选择“4字节整数”。从窗口左上角显示的十六进制地址中减去4,然后在地址框中输入该地址。或者单击滚动条向上箭头,查看第一行中的最后一个值。这是拥有锁的线程的Thread.ManagedThreadId。请注意,这并不总是有效,对象中的这个字段也用于其他目的(例如GetHashCode)。

了解线程的托管标识现在让您查看线程的“调试+ Windows +线程”窗口。但是,只有在VS2010中,早期版本才会在此窗口中显示线程的托管标识。对于这些,您需要添加一些显示Thread.CurrentThread.ManagedThreadId值的跟踪代码。添加跟踪代码通常是解决线程问题的有用技术。然而,这个代码改变了时间并且可能使线程问题消失,这是非常危险的。许多跟踪监听器也有一个隐含的锁。