由静态块中的thread.join()引起的死锁

我遇到了一个死锁场景,可以概括为下面显示的StaticDeadlock类。

这个简单的程序将冻结在o.getClass() 。 这是我对发生的事情的猜测,但有人可以更好地解释一下吗?

1)程序进入StaticDeadlock静态块

2) 线程启动

3) 主线程等待线程完成,因此无法完成静态块

4)在线程内部访问StaticDeadlock.o但StaticDeadlock的静态块尚未完成。 因此程序会冻结吗?

public class StaticDeadlock { private static final Object o = new Object(); static { MyThread thread = new MyThread(); thread.start(); try { thread.join(); } catch (InterruptedException e) { e.printStackTrace(); } } public static void main (String[] args) { System.out.println("all is well."); } static class MyThread extends Thread { @Override public void run () { System.out.println("inside mythread"); o.getClass(); } } } 

是的,这就是它。 新线程在访问静态成员之前等待StaticDeadlock的类初始值StaticDeadlock完成。 有关更多详细信息,请参阅Java语言规范的第12.4.2节 ,特别是这些步骤:

  1. 在Class对象上同步(第14.19节),该对象表示要初始化的类或接口。 这涉及等到当前线程可以获得该对象的锁定(第17.1节)。

  2. 如果某个其他线程正在对类或接口进行初始化,则等待此Class对象(暂时释放锁定)。 当前线程从等待中唤醒时,重复此步骤。

  3. 如果当前线程正在对类或接口进行初始化,那么这必须是初始化的递归请求。 释放Class对象上的锁定并正常完成。

  4. 如果类或接口已初始化,则无需进一步操作。 释放Class对象上的锁定并正常完成。

它甚至不会通过第二个线程中的第1步,因为第一个线程具有锁定并且不会释放它。

请注意,它不会调用导致问题的getClass() – 执行任何需要o值的操作会使第二个线程等到类初始化程序完成,这当然不会发生,因为第一个线程正在等待第二个线程线程完成。