I found article(https://habr.com/company/odnoklassniki/blog/255067/) from the @apangin(https://stackoverflow.com/users/3448419/apangin) on my native langugage but I am not able to understand it. Explanation is very concise
Let's consider that code:
static class A {
static final B b = new B();
}
static class B {
static final A a = new A();
}
public static void main(String[] args) {
new Thread(A::new).start();
new B();
}
You could try to run that code. On my pc it leads to deadlockwith 75% probability/
So we have 2 threads:
Thread_1 is creating instance of A
Thread_2(main thread) is creating instance of B
It is first access to class so it leads(might lead) to concurrent classes A and B initialization.
Next step is not clear for me. Could you explain it?
JVM Specification §5.5 describes class initialization procedure in detail. It consists of 12 steps.
At step 6 the class is marked as "in progress of initialization by the current thread".
- Otherwise, record the fact that initialization of the Class object for C is in progress by the current thread, and release LC.
So Thread_1
starts initializing class A
and marks it as being initialized by Thread_1
. Similarly class B
is marked as being initialized by Thread_2
.
At step 9 the static initializer is invoked.
- Next, execute the class or interface initialization method of C.
The static initializer of A
creates an instance of B
, which is not yet fully initialized, so Thread_1
(while in progress of initializing A
) recursively starts the procedure of initializing B
.
At step 2 of the procedure it detects that class B
is in progress of initialization by different thread and blocks.
- If the Class object for C indicates that initialization is in progress for C by some other thread, then release LC and block the current thread until informed that the in-progress initialization has completed, at which time repeat this procedure.
Symmetrically Thread_2
starts initialization of A
, detects that it is already being initialized by different thread and also blocks at step 2. Both threads are blocked waiting for each other.
Note: the class is marked as fully initialized and notifies other threads after successful invocation of static initializer, which never happens in this case.
- If the execution of the class or interface initialization method completes normally, then acquire LC, label the Class object for C as fully initialized, notify all waiting threads, release LC, and complete this procedure normally.