如何找出哪个线程持有监视器? [英] How to find out which thread holds the monitor?

查看:154
本文介绍了如何找出哪个线程持有监视器?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的应用程序正在使用Gson 2.2POJOs转换为JSON.在进行负载测试时,我偶然发现Gson构造函数中阻塞了许多线程:

My application is using Gson 2.2 for converting POJOs to JSON. When I was making a load test I stumbled upon a lot of threads blocked in Gson constructor:

"http-apr-28201-exec-28" #370 daemon prio=5 os_prio=0 tid=0x0000000001ee7800 nid=0x62cb waiting for monitor entry [0x00007fe64df9a000]
    java.lang.Thread.State: BLOCKED (on object monitor)
    at com.google.gson.Gson.<init>(Gson.java:200)
    at com.google.gson.Gson.<init>(Gson.java:179)

线程转储不显示任何持有[0x00007fe64df9a000] monitor的线程. 我如何找出谁持有它?

Thread dump does NOT show any threads holding [0x00007fe64df9a000] monitor. How can I find out who holds it?

Gson代码我在Linux上使用JRE 1.8.0_91

推荐答案

tl; dr 集合.

我没有全部真相,但我希望提供一些见识.

I do not have the whole truth but I hope to provide some pieces of insight.

首先要要意识到的是,方括号[0x00007fe64df9a000]中的数字不是监视器的地址.对于转储中的所有线程,甚至处于运行状态的线程,都可以看到括号中的数字.该数字也不会改变.我的测试转储中的示例:

First thing to realize is that the number in brackets, [0x00007fe64df9a000], is not the adress of a monitor. The number in brackets can be seen for all threads in a dump, even threads that are in running state. The number also does not change. Example from my test dump:

main" #1 prio=5 os_prio=0 tid=0x00007fe27c009000 nid=0x27e5c runnable [0x00007fe283bc2000]
   java.lang.Thread.State: RUNNABLE
        at Foo.main(Foo.java:12)

我不确定数字的含义,但是此页面暗示它是

I am not sure what the number means, but this page hints that it is:

...指向Java VM内部线程结构的指针.除非您正在调试实时Java VM或核心文件,否则通常没有兴趣.

... the pointer to the Java VM internal thread structure. It is generally of no interest unless you are debugging a live Java VM or core file.

尽管解释的跟踪格式有些不同,所以我不确定我是正确的.

Although the format of the trace explained there is a bit different so I am not sure I am correct.

显示实际监视器地址时转储的外观:

The way a dump looks when the adress of the actual monitor is shown:

"qtp48612937-70" #70 prio=5 os_prio=0 tid=0x00007fbb845b4800 nid=0x133c waiting for monitor entry [0x00007fbad69e8000]
   java.lang.Thread.State: BLOCKED (on object monitor)
        at sun.nio.ch.ServerSocketChannelImpl.accept(ServerSocketChannelImpl.java:233)
        - waiting to lock <0x00000005b8d68e90> (a java.lang.Object)

请注意跟踪中的waiting to lock行,并且监视器的地址与方括号中的数字不同.

Notice the waiting to lock line in the trace and that the adress of the monitor is different from the number in brackets.

我们看不到所涉及的监视器的地址这一事实表明该监视器仅存在于本机代码中.

The fact that we cannot see the adress of the monitor involved indicates that the monitor exists only in native code.

其次,所涉及的Gson代码根本不包含任何同步.该代码仅向ArrayList添加了一个元素(假设未执行任何字节码操作,并且在低级别未进行任何恶意操作).也就是说,在此调用中看到线程等待标准同步监视器是没有意义的.

Secondly, the Gson code involved does not contain any synchronization at all. The code just adds an element to an ArrayList (assuming no bytecode manipulation has been done and nothing fishy is being done at low level). I.e., it would not make sense to see the thread waiting for a standard synchronization monitor at this call.

我发现一些我编写了一个简单的测试程序,试图通过向数组列表中添加很多元素来重现它:

I wrote a simple test program to try to reproduce it by just adding a lot of elements to an array list:

List<String> l = new ArrayList<>();
while (true) {
    for (int i = 0; i < 100_100; i++) {
            l.add("" + i);
    }
    l = new ArrayList<>();
}

然后我获取了该程序的线程转储.有时我遇到以下跟踪:

Then I took thread dumps of this program. Occasionally I ran into the following trace:

"main" #1 prio=5 os_prio=0 tid=0x00007f35a8009000 nid=0x12448 waiting on condition [0x00007f35ac335000]
   java.lang.Thread.State: RUNNABLE
      at Foo.main(Foo.java:10)   <--- Line of l.add()

虽然与OP的踪迹不同,但是在不涉及同步的情况下拥有线程waiting on condition很有趣.我使用较小的堆会更频繁地体验它,这表明它可能与GC有关.

While not identical to the OP's trace, it is interesting to have a thread waiting on condition when no synchronization is involved. I experienced it more frequently with a smaller heap, indicating that it might be GC related.

另一种可能是包含同步的代码已经JIT编译,从而使您无法看到监视器的实际地址.但是,我认为这种可能性较小,因为您在ArrayList.add上遇到过这种情况.如果是这样,我将无法找到监视器的实际持有人.

Another possibility could be that code that contains synchronization has been JIT compiled and that prevents you from seeing the actual adress of the monitor. However, I think that is less likely since you experience it on ArrayList.add. If that is the case, I know of no way to find out the actual holder of the monitor.

这篇关于如何找出哪个线程持有监视器?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆