6

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>

我的问题:

线程转储中,为什么没有行- locked <0x00002aaaf4394580>

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

在我读过的所有死锁文档(示例)中,对于每一- parking to wait for <0x123>行,总是有- locked <0x123>一行。所以我开始怀疑是 JVM 错误。我是不是误会了什么?

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

4

5 回答 5

4

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

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

于 2012-06-28T07:31:29.890 回答
0

Marko Topolnik 的回答是正确的。

至于您的问题的解决方案,JProfiler将向您显示一个完整的线程图和监视器,以了解涉及 java.util.concurrent 包中的锁的锁定情况。

免责声明:我公司开发JProfiler

于 2012-06-28T08:29:33.390 回答
0

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

锁可以是内置对象监视器、可拥有的同步器或与同步器关联的 Condition 对象。

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

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

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

于 2012-09-07T05:22:25.610 回答
0

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

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

于 2013-08-28T14:09:12.357 回答
0

堆栈跟踪显示 0x00002aaaf4394580 未被任何线程锁定。这可能是由于Java 错误 #6822370 造成的。这一观察结果应该为投票的答案增加封闭性。

于 2014-07-23T16:30:06.500 回答