2011-07-13 42 views
1

我遇到了一个死锁场景,可以概括为下面显示的StaticDeadlock类。由静态块中的thread.join()导致的死锁

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

1),程序进入StaticDeadlock静块

2)螺纹开始

3)主线程置于等待螺纹完成,因此不能完成静态块

4)内部线程它访问 StaticDeadlock.o但StaticDeadlock的静态块是n还没完成。因此程序冻结?

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(); 
      } 
     } 

    } 

回答

7

是的,就是这么多。新线程正在等待StaticDeadlock的类初始化程序在它访问静态成员之前完成。见section 12.4.2 of the Java Language Specification更多细节,尤其是下列步骤:

  1. 同步(§14.19)表示的类或接口被初始化类对象上。这包括等待,直到当前线程可以获得该对象的锁(第17.1节)。

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

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

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

它甚至不会在第二个线程过去的第1步,作为第一个线程具有锁,不会释放它。

注意,它不是叫getClass()这会导致问题 - 做任何这需要o值会使第二个线程等待,直到类初始化完成后,这当然不会发生,因为第一个线程等待第二个线程完成。