Search code examples
javamultithreadingjvminitializationdeadlock

Class initialization deadlock mechanism explanation


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?


Solution

  • 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".

    1. 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.

    1. 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.

    1. 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.

    1. 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.