【问题标题】:"Found 1 deadlock" but trace shows that not locked by any thread“发现 1 个死锁”但跟踪显示没有被任何线程锁定
【发布时间】:2012-06-29 16:36:51
【问题描述】:

JVM 告诉我发生了死锁:

Found one Java-level deadlock:
=============================
"TP-Processor107":
  waiting for ownable synchronizer 0x00002aaaf58e70f0, (a java.util.concurrent.locks.ReentrantReadWriteLock$NonfairSync),
  which is held by "indexTrackerThread3"
"indexTrackerThread3":
  waiting for ownable synchronizer 0x00002aaaf4394580, (a java.util.concurrent.locks.ReentrantReadWriteLock$NonfairSync),
  which is held by "TP-Processor16"
"TP-Processor16":
  waiting for ownable synchronizer 0x00002aaaf58e70f0, (a java.util.concurrent.locks.ReentrantReadWriteLock$NonfairSync),
  which is held by "indexTrackerThread3"

我们可以看到indexTrackerThread3 正在等待TP-Processor16 持有的资源,反之亦然。这确实是一个僵局。

我们可以看到indexTrackerThread3正在等待0x00002aaaf4394580

"indexTrackerThread3":
    - parking to wait for  <0x00002aaaf4394580>

我的问题:

the threads dump,为什么没有- locked &lt;0x00002aaaf4394580&gt;行?

似乎 0x00002aaaf58e70f0 实际上没有被任何线程锁定。是什么锁定了它?

在我阅读过的所有死锁文档 (example) 中,对于每一不同的 - parking to wait for &lt;0x123&gt; 行,总是有一个 - locked &lt;0x123&gt; 行。所以我开始怀疑是 JVM 错误。我是不是误会了什么?

注意:很抱歉链接到 pastebin,但如果没有完整的转储,这个问题是无法回答的。为简洁起见,我删除了所有包含“at”的行,它们不包含任何锁定信息。

【问题讨论】:

    标签: java multithreading thread-safety jvm deadlock


    【解决方案1】:

    java.util.concurrent 包使用了语言外的本地停放机制(以及其他本地机制,例如原子比较和交换)。你可以看到我在说什么here

    您描述的通常出现在线程转储中的模式源于经典的 Java 习惯用法synchronized(lock) { lock.wait(); }

    【讨论】:

    • 感谢您的链接!我现在已经熟悉了 Unsafe 类。即使通过调用 Unsafe.park 完成,锁定仍然来自 Java 调用,那么为什么locked &lt;0x123&gt; 部分不在该行写入?我将不胜感激任何有关 id 不存在的特定问题的文档。
    【解决方案2】:

    Marko Topolnik 的回答是正确的。

    至于您的问题的解决方案,JProfiler 将向您展示一个完整的线程图,并针对涉及 java.util.concurrent 包中的锁的锁定情况进行监控。

    免责声明:我公司开发JProfiler

    【讨论】:

      【解决方案3】:

      不同的东西会导致 java 线程死锁,监视器,也就是 synchronized 关键字,只是一回事。

      A lock can be a built-in object monitor, an ownable synchronizer, or the Condition object associated with synchronizers.

      您还可以深入了解 ThreadMXBean.findDeadlockedThreads 和 ThreadMXBean.findMonitorDeadlockedThreads 的定义以获取更多信息。

      就我而言,它是监视器锁定和 java 5 锁定。

      在线程转储中,waiting to lock &lt;0x123&gt;locked &lt;0x123&gt; 组合仅用于监视器锁定。 使用 java 5 锁定,您只能获得第一部分。 像parking to wait for &lt;0x456&gt; 这样的东西。然后您在线程转储中搜索一些 0x456,但无处可寻。这令人困惑。

      【讨论】:

        【解决方案4】:

        此类死锁的线程转储分析的复杂性主要是由于使用了 java.util.concurrent 包。这是为了摆脱传统的、侵入性的同步 Java 对象的方式。例如,当您希望将 WRITE 操作限制为单个 Thread 模型同时允许并发 READ 操作时,此包非常有用。从性能调优的角度来看,这种方法非常棒,副作用是在处理并发问题时增加了线程转储分析过程的复杂性。

        我建议您也查看以下文章。它描述了诸如hidden Java deadlock 之类的问题,其中 JVM 甚至无法检测到死锁(由于 READ 锁通常没有设计为具有所有权概念)。以示例 Java 程序为例。

        【讨论】:

          【解决方案5】:

          堆栈跟踪显示 0x00002aaaf4394580 未被任何线程锁定。这可能是由于Java bug #6822370 而发生的。此观察结果应为voted answer 添加闭包。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2014-05-28
            • 1970-01-01
            • 2012-04-12
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多