Thread_1 создает экземпляр A
Да.И ключевое слово new
требует инициализации класса A
.
Thread_2 (основной поток) создает экземпляр B
Да.И ключевое слово new
также требует инициализации класса B
.
Но существует зависимость между этими классами в clinit
(static
блоки и static
поля инициализации).
С JLS.12.4.2.Подробная процедура инициализации :
Для каждого класса или интерфейса C имеется уникальная блокировка инициализации LC.Отображение из C в LC оставлено на усмотрение реализации виртуальной машины Java.Тогда процедура инициализации C выглядит следующим образом:
- Синхронизация при блокировке инициализации , LC, для C. Это включает ожидание, пока текущий поток может получить LC .
(другие шаги опущены, но первый - самый важный)
Итак, вот что может произойти:
Thread_1
:
- Видит, что он должен создать экземпляр класса
A
(new
) - Начинает инициализацию класса
A
(первое использование A
класса) - Получает блокировку инициализации класса
A
.
(Здесь планировщик потока ОС решает, что пришло время приостановить Thread_1
и дать некоторое время потоку main
)
И поток main
:
- Видит, что он должен создать экземпляр класса
B
(new
) - Начинает инициализацию класса
B
(первое использование класса B
) - Получает блокировку инициализации класса
B
.
Внешний видПланировщик объявлений теперь приостанавливает поток main
и дает время Thread_1
.
Thread_1
продолжается:
Он видит
static final B b = new B();
Не разрешено создавать новый экземпляр
B
, поскольку класс
B
еще не инициализирован. Он пытается получить блокировку инициализации класса
B
, но блокировка удерживается потоком
main
.
Планировщик потока снова приостанавливает Thread_1
и дает некоторыевремя до main
.И это продолжается:
Он видит
static final A a = new A();
Не разрешено создавать новый экземпляр
A
, потому что класс
B
еще не инициализирован. Он пытается получить блокировку инициализации класса
A
, но блокировка удерживается потоком
Thread_1
.
Итак, вот тупик:
-
Thread_1
содержит блокировку инициализации A
и хочет получить блокировку инициализации класса B
- Поток
main
содержит блокировку инициализации B
и хочет получить A
блокировка инициализации класса