为什么这段代码会产生死锁?

class A { static final int i; static { i = 128; Thread t = new Thread() { public void run() { System.out.println("i=" + i); } }; t.start(); try { t.join(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } } public class MainTesting { public static void main(String[] args) { A a = new A(); System.out.println("finish"); } } 

我永远不会得到finish打印和我的价值。 为什么会这样?

首先从线程1(“主”线程)开始,然后开始为A类执行静态初始化程序。

在该静态初始化程序中,然后启动一个新线程(2),该线程使用A类中的某些内容。 这意味着线程2需要等到A类完成初始化才能继续进行,如JLS第12.4.2节所述 :

如果C的Class对象指示某个其他线程正在为C进行初始化,则释放LC并阻止当前线程,直到通知正在进行的初始化已完成,此时重复此步骤。

但是, A的静态初始化程序在完成之前等待线程2完成(通过调用join() ),导致死锁:静态初始化程序无法完成,直到线程2完成,并且线程2无法完成,直到静态初始化程序已完成…

Upshot:不要这样做:)

隐式同步加载类和静态块这意味着在初始化时,您无法访问另一个线程中的类中的任何内容。 在这种情况下,初始化正在等待使用Ai的线程。 换句话说,它正在等待第一个线程完成静态块。

注意:它不使用普通锁,并且线程声称处于Runnable状态,即使它已死锁。

 2013-06-21 11:20:40 Full thread dump Java HotSpot(TM) 64-Bit Server VM (23.21-b01 mixed mode): "Thread-0" prio=6 tid=0x000000000d55d000 nid=0x3cc4 in Object.wait() [0x000000000dbdf000] java.lang.Thread.State: RUNNABLE at Main$1.run(Main.java:14) <- where Ai is referenced. "main" prio=6 tid=0x00000000022df000 nid=0x3284 in Object.wait() [0x000000000257e000] java.lang.Thread.State: WAITING (on object monitor) at java.lang.Object.wait(Native Method) - waiting on <0x00000007d5610448> (a Main$1) at java.lang.Thread.join(Thread.java:1258) - locked <0x00000007d5610448> (a Main$1) at java.lang.Thread.join(Thread.java:1332) at Main.(Main.java:19) at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Class.java:188) at com.intellij.rt.execution.application.AppMain.main(AppMain.java:113)