2016-06-22 2 views
2

У меня есть три класса.Получение взаимоблокировки в Java-коде

BaseClass.java

public class BaseClass { 

    static { 
     load(); 
    } 

    public static void init() { 
     System.out.println("base init"); 
    } 

    private static void load() { 
     System.out.println("In load method of base class"); 
     DerivedClass dc = new DerivedClass(); 
     System.out.println("Object creation done."); 
    } 

} 

DerivedClass.java

public class DerivedClass extends BaseClass { 

    public DerivedClass() { 
     System.out.println("derived class constructor"); 
    } 

    public static boolean isSynthetic(String _attr) { 
     return true; 
    } 
} 

Helper.java

public class Helper { 

    public static void main(String[] args) { 
     Thread t = new Thread() { 
      public void run() { 
       BaseClass.init(); 
      }; 
     }; 
     t.start(); 
     System.out.println("calling static method of derived class.."); 
     System.out.println(DerivedClass.isSynthetic("test")); 
    } 

} 

Когда я выполнение основного метода из Helper.java, я получаю следующий результат -

вызова статического метода производного класса ..

В методе нагрузки базового класса

После этого исполнения является прекращением но процесс все еще работает. Так что кажется, что есть какой-то тупик, но я не понимаю, почему это так. Помощь нужна.

+0

Приведенная ниже ссылка ответит на ваш вопрос. [http://stackoverflow.com/questions/10698516/behavior-of-static-blocks-with-inheritance](http://stackoverflow.com/questions/10698516/behavior-of-static-blocks-with-inheritance) –

ответ

2

Когда BaseClass ссылается в первый раз, когда загрузчик классов запускает и хочет настроить класс для использования. Так он загружает класс и запускает статический инициализатор Блокировать

static { 
    load(); 
} 

Это вызывает load -метод и там вы пытаетесь создать объект типа DerivedClass. Сначала попробуйте вызвать конструктор super(), т. Е. Метод класса BaseClass, но BaseClass еще не полностью инициализирован, поскольку его статический инициализатор не завершил => тупик.

Редактировать: Основываясь на вашем комментарии, я сделал еще несколько исследований. На самом деле все не так просто, как я предполагал. JVM способен работать с рекурсивной инициализацией, поэтому нет проблем в однопоточном случае. Описание процесса инициализации класса можно найти в разделе 5.5 спецификации JVM.

Что является виновником здесь, является фактически условием гонки между двумя процессами инициализации.

Резьба 1 достигает DerivedClass.isSynthetic("test") и запускает инициализацию DerivedClass.

Между тем нить 2 достигает BaseClass.init() и запускает инициализацию BaseClass.

При инициализации DerivedClass поток 1 распознает, что он должен инициализировать суперкласс. Поскольку инициализация BaseClass уже выполняется потоком 2, поток 1 должен дождаться завершения.

При инициализации BaseClass нить 2 достигает DerivedClass dc = new DerivedClass();. Поскольку инициализация DerivedClass уже ведется по потоку 1, поток 2 должен дождаться завершения.

Так что это классический тупик, где два потока пытаются ввести две критические кодировки («инициализация класса X») в разном порядке (BaseClass-> DerivedClass vs.DerivedClass-> BaseClass) и заканчивая ожидание друг друга.

Добавление некоторых Thread.sleep(100); в соответствующие места также покажет вам, что это действительно состояние гонки. Во время моих тестов иногда программа выполнялась успешно, несмотря на циклическую зависимость во время инициализации.

+0

То, что вы объяснили, кажется возможным, но тогда почему «System.out.println (DerivedClass.isSynthetic (« test »)); здесь статический метод производного класса также находился в состоянии взаимоблокировки. и когда я удаляю вызов статического метода производного класса, выполнение выполняется отлично, и я получаю вывод как:
вызов В базовом классе конструктор производного класса Создание объекта. base init –

+0

@Rahulkhandelwal Вы правы, JVM более изощрен, чем я думал. Я добавил некоторые объяснения по реальной причине. –

+0

Спасибо за объяснение. Это действительно полезно. –

Смежные вопросы