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

时间:2011-07-13 22:12:58

标签: java multithreading deadlock

我遇到了一个死锁场景,可以概括为下面显示的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();
            }
        }

    }

1 个答案:

答案 0 :(得分:8)

是的,就是这样。新线程在访问静态成员之前等待StaticDeadlock的类初始值设定项完成。有关详细信息,请参阅section 12.4.2 of the Java Language Specification,特别是这些步骤:

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

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

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

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

  8.   

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

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