Возможно, что выполнение этих двух операторов переплетено:
Thread 1: a.methodA(b); //inside the constructor
Thread 2: b.methodB(a); //inside run()
для выполнения a.methodA()
, поток 1 должен получить блокировку для объекта A
.
для выполнения b.methodB()
, поток 2 должен получить блокировку для объекта B
.
Чтобы поток 101 * * мог затем вызывать синхронизированный метод для экземпляра b
, ему необходимо получить блокировку для b
, удерживаемую потоком 2, что заставит поток 1 ждать, пока этот замок освобожден.
Для того чтобы methodB()
в Thread2 мог вызывать синхронизированный метод в экземпляре a
, ему необходимо получить блокировку, удерживаемую в a
потоком 1, что также заставит поток 2 ожидать.
Поскольку каждый поток удерживает блокировку, которую хочет другой поток, возникает тупиковая ситуация, когда ни один из потоков не может получить блокировку, которую он хочет, и ни один из потоков не снимет блокировки, которые удерживает .
Важно понимать, что этот код не будет вызывать взаимоблокировку в 100% случаев, когда вы его выполняете - только при выполнении четырех важных шагов (Thread1 удерживает блокировку A и пытается получить B, а Thread 2 удерживает блокировку B и пытается получить а) выполняются в определенном порядке. Запустите этот код достаточно много раз, и этот порядок обязательно произойдет.