多个Java线程似乎锁定了同一个监视器?

jfr*_*ius 11 java concurrency multithreading locking

在Java threaddump中,我发现了以下内容:

"TP-Processor184" daemon prio=10 tid=0x00007f2a7c056800 nid=0x47e7 waiting for monitor entry [0x00007f2a21278000]
   java.lang.Thread.State: BLOCKED (on object monitor)
    at org.apache.jackrabbit.core.state.SharedItemStateManager.getNonVirtualItemState(SharedItemStateManager.java:1725)
    - locked <0x0000000682f99d98> (a org.apache.jackrabbit.core.state.SharedItemStateManager)
    at org.apache.jackrabbit.core.state.SharedItemStateManager.getItemState(SharedItemStateManager.java:257)

"TP-Processor137" daemon prio=10 tid=0x00007f2a7c00f800 nid=0x4131 waiting for monitor entry [0x00007f2a1ace7000]
   java.lang.Thread.State: BLOCKED (on object monitor)
    at org.apache.jackrabbit.core.state.SharedItemStateManager.getNonVirtualItemState(SharedItemStateManager.java:1725)
    - locked <0x0000000682f99d98> (a org.apache.jackrabbit.core.state.SharedItemStateManager)
    at org.apache.jackrabbit.core.state.SharedItemStateManager.getItemState(SharedItemStateManager.java:257)
Run Code Online (Sandbox Code Playgroud)

这里的重点是两个线程都锁定了监视器<0x0000000682f99d98>(无论它们现在正在等待两个不同的其他监视器).

在查看Thread Dump Analyzer时,如果选择了该监视器,它实际上会在底部显示"Threads locking monitor:2",并且"2 Threads s slock".有关屏幕截图,请参阅https://lh4.googleusercontent.com/-fCmlnohVqE0/T1D5lcPerZI/AAAAAAAAD2c/vAHcDiGOoMo/s971/locked_by_two_threads_3.png,我不允许在此处粘贴图片.

这是否意味着关于监视器锁定信息,threaddumps不是原子的?我无法想象这真的是JVM的锁定错误(1.6.0_26-b03).

类似的问题已经在几个线程中被问到可以锁定Java中的同一个监视器吗?,但我的答案并没有看到多个线程锁定同一个监视器的真正意义,即使他们可能正在等待其他一些.

2014年5月13日更新:

更新的问题多个线程持有相同的锁?有代码重现行为,@ rssx已根据他的答案提交了一份相应的错误报告https://bugs.openjdk.java.net/browse/JDK-8036823.

rxg*_*rxg 2

在分析激烈竞争的锁时,您可能会在 JVM 的堆栈跟踪例程中遇到一个装饰性错误 - 它可能与此错误相同,也可能不同。

事实上,您的两个线程实际上都没有成功获取 的锁SharedItemStateManager,正如您从它们报告的事实中看到的那样waiting for monitor entry。错误在于,在这两种情况下,在堆栈跟踪中,它们应该报告waiting to lock而不是locked.

分析像这样的奇怪堆栈跟踪时的解决方法是始终检查声称拥有locked对象的线程是否也在等待获取同一对象上的锁。

waiting for monitor entry(不幸的是,此分析需要将堆栈跟踪中的行号与源代码进行交叉引用,因为标头中的数字与堆栈跟踪中的行之间没有关系locked。根据此 Oracle 文档0x00007f2a21278000,行中的数字TP-Processor184" daemon prio=10 tid=0x00007f2a7c056800 nid=0x47e7 waiting for monitor entry [0x00007f2a21278000] 指的是对线程有效堆栈区域的估计。所以它看起来像一个监视器 ID,但它不是 - 并且您可以看到您提供的两个线程位于堆栈中的不同地址)。