<clinit>死锁的问题
youlong699
2013-05-01
静态变量初始化的死锁的一个疑问。
这个是毕大神的一个case http://hellojava.info/?p=88, 然后研究了下,还不太明白。主要是jstack dump里线程的状态不理解。 我找了个初始化死锁的线程: "call-cStr" prio=6 tid=0x0257cc00 nid=0x18a4 in Object.wait() [0x04c3f000] java.lang.Thread.State: RUNNABLE at C.<clinit>(StaticInit.java:40) at StaticInit$2.run(StaticInit.java:13) at java.lang.Thread.run(Thread.java:662) "call-bStr" prio=6 tid=0x0257a400 nid=0x1ddc in Object.wait() [0x04baf000] java.lang.Thread.State: RUNNABLE at B.<clinit>(StaticInit.java:28) at StaticInit$1.run(StaticInit.java:7) at java.lang.Thread.run(Thread.java:662) 代码是这样的: public class StaticInit { public static void main(String[] arg){ Thread th1 = new Thread(new Runnable(){ public void run(){ System.out.println(B.bStr); } },"call-bStr") ; Thread th2 = new Thread(new Runnable(){ public void run(){ System.out.println(C.cStr); } },"call-cStr"); th1.start(); th2.start(); } } class B { static{ try{ System.out.println("Binit start"); Thread.sleep(1000); }catch(InterruptedException ex){ } System.out.println("b->cStr " + C.cStr); } static String bStr = "bStr" ; } class C { static{ try{ System.out.println("Cinit start"); Thread.sleep(1000); }catch(InterruptedException ex){ } System.out.println("c->b.bStr " + B.bStr); } static String cStr ="cStr"; } 疑问点在于 "call-cStr" prio=6 tid=0x0257cc00 nid=0x18a4 in Object.wait() [0x04c3f000] java.lang.Thread.State: RUNNABLE State 是 RUNNABLE, 然后第一行又是输出的Object.wait(), 这个岂不是不一致了? 另外, 对于这种jvm加锁的,有没有好办法看到它的锁? 如果调用了本地代码导致了死锁,是不是jstack都表现为这种情况? :) |
|
RednaxelaFX
2013-05-01
youlong699 写道 疑问点在于
"call-cStr" prio=6 tid=0x0257cc00 nid=0x18a4 in Object.wait() [0x04c3f000] java.lang.Thread.State: RUNNABLE State 是 RUNNABLE, 然后第一行又是输出的Object.wait(), 这个岂不是不一致了? 另外, 对于这种jvm加锁的,有没有好办法看到它的锁? 如果调用了本地代码导致了死锁,是不是jstack都表现为这种情况? 是的,Thread.State为RUNNABLE但前面显示Object.wait()是不一致,这个显示内容其实有误。Object.wait()是正确的。 HotSpot VM在显示stack trace时,对VM内锁住对象的情况处理得不好,无法将其正确反映出来。这包括VM内直接用ObjectLocker来锁对象的,也包括通过JNI的MonitorEnter来锁对象的情况。以前写过个笔记演示这个状况:https://gist.github.com/rednaxelafx/2204011。还写过另一个笔记,说ThreadMXBean获取锁信息的方法可以正确处理native frame锁住对象的情况:https://gist.github.com/rednaxelafx/2223542 jstack输出的stack trace还有另外一种很奇葩的情况,就是可能会有多个线程看起来锁住了同一个对象。以前我也写过相关笔记:http://mail.openjdk.java.net/pipermail/hotspot-runtime-dev/2012-July/004106.html |
|
ticmy
2013-05-02
有必要提醒一点的是,bluedavy的那个问题不是因为<clinit>死锁导致的。
|
|
youlong699
2013-05-04
RednaxelaFX 写道 jstack输出的stack trace还有另外一种很奇葩的情况,就是可能会有多个线程看起来锁住了同一个对象。以前我也写过相关笔记:http://mail.openjdk.java.net/pipermail/hotspot-runtime-dev/2012-July/004106.html 谢R大指点。 又长见识了:) |
|
youlong699
2013-05-04
ticmy 写道 有必要提醒一点的是,bluedavy的那个问题不是因为<clinit>死锁导致的。
我本以为我看懂了。。 被你这么一说又不懂了。 可否进一步指点一下? |
|
ticmy
2013-05-04
youlong699 写道 ticmy 写道 有必要提醒一点的是,bluedavy的那个问题不是因为<clinit>死锁导致的。
我本以为我看懂了。。 被你这么一说又不懂了。 可否进一步指点一下? 后来他不是又发了一篇文章解释了 |
|
youlong699
2013-05-05
ticmy 写道 我本以为我看懂了。。 被你这么一说又不懂了。 可否进一步指点一下? 后来他不是又发了一篇文章解释了 后来又发了两篇文章,一个cpu sy高排查的case http://hellojava.info/?p=99 和 cpu sy高case和static case(续) http://hellojava.info/?p=101 这两个都没有对死锁的这个case再做解释吧? 第二篇对 static final 的编译做了说明。 |
|
m635674608
2013-06-01
能解释下这个情况吗????
|
|
youlong699
2013-07-11
m635674608 写道 能解释下这个情况吗????
恩, 最近忙没来逛。就是<clinit>死锁的问题,这里隐蔽的原因在于是锁在了静态字段,而非静态初始化块。但是静态字段的初始化会被收集到<clinit>里。 关于<clinit>加锁可以看下示例初始化相关的资料。 《深入理解jvm虚拟机》里也有比较全面的介绍 |