【问题标题】:How do I find the lockholder (reader) of my ReaderWriterLock in windbg如何在 windbg 中找到我的 ReaderWriterLock 的锁持有者(阅读器)
【发布时间】:2009-05-20 04:05:09
【问题描述】:

我有一个 .Net 进程的转储,该进程由于死锁而挂起(gui 线程不再响应,并且我的日志显示某些线程已停止响应)。我拍了一张快照,现在正在windbg中查看它,所有线程都在等待最后一个。使用 !clrstack -p 查看那个线程的堆栈跟踪,我可以看到它正在尝试获取 ReaderWriterLock 上的写入

我如何知道哪个线程持有该锁,以便我可以开始弄清楚死锁是如何发生的?

谢谢

[编辑] .Net1.1 sos.dll 中显然有一个命令 !rwlocks 来帮助解决这个问题,但 .Net2.0 版本中没有。狩猎继续

【问题讨论】:

    标签: .net windbg deadlock readerwriterlock


    【解决方案1】:

    我不是很确定,但你也许可以使用 !SyncBlk 来查看同步块对象,如果你在没有任何参数的情况下调用它,我认为你应该看到线程拥有的同步块。

    如果你有一个同步块死锁,扩展 SOSEX 可能是你需要的。这个扩展提供了命令 !dlk 来显示哪些线程正在等待哪些锁。但这仅适用于同步块,不会检测到其他同步对象上的死锁,如果您使用 lock() (Monitor.Enter),这对您来说应该不是问题。

    【讨论】:

    • 我们正在使用内置的 ReaderWriterLocks,它不会出现在 !dlk 上
    【解决方案2】:

    试试sosex 和 !dlk

    【讨论】:

    • !dlk 仅在您有同步块(如 lock(myObject.SyncRoot){} 或 Monitors)时有效,而不适用于 ReaderWriterLocks
    【解决方案3】:

    我不久前在这里发布了一个类似的主题,Using C# is it possible to test if a lock is held on a file

    我参考了许多文章等,但是等待链遍历 (WCT) 可以帮助您,这有点棘手,但这篇 msdn mag bugslayer 文章展示了如何在托管上下文中在 windbg 中使用 WCT。

    【讨论】:

    • 不错的文章,可惜它需要我们运行 Vista,但总有一天我们会到达那里......奇怪的是即使没有对 WaitForMultipleObjects 的支持
    【解决方案4】:

    到目前为止,最好的方法是查看所有线程堆栈的 !dso,并查看哪些引用了锁。之后的快速检查让我们能够追踪哪些线程持有锁。虽然真的不是一个漂亮或快速的方法......

    【讨论】:

      【解决方案5】:

      提供可追溯性的一种方法是将您的锁包装到 IDisposable 接口中并替换:

      lock(mylock) { ... }

      使用(新的 DisposeableLock()) { ... }

      您可以将构造函数和 Dispose() 方法记录到控制台、log4net 或其他一些机制。这将允许您查看正在锁定的内容以及正在阻止的内容。

      【讨论】:

      • 我们的应用程序中有很多锁,因此每个线程的两行日志记录很快就会加起来。该问题似乎每两周仅在十个用户中发生一次,并且从未在开发环境中发生过,因此这是一种相当昂贵的方法。但如果没有其他方法......
      • IDisposable 锁可能会降低性能,因为每个“DisposableLock”都必须经过 GC 的最终确定轮次,然后是 GC 的实际收集轮次 = 有时会导致内存不足由于分配内存的速度比到达 GC 队列的速度快。
      猜你喜欢
      • 1970-01-01
      • 2011-07-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多