类初始化死锁机制说明 [英] Class initialization deadlock mechanism explanation

查看:157
本文介绍了类初始化死锁机制说明的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我找到了文章( https://habr.com/company/odnoklassniki/blog/255067/)来自@apangin( https://stackoverflow.com/users/3448419/apangin )用我的母语,但我听不懂.解释很简洁

让我们考虑一下该代码:

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();
}

您可以尝试运行该代码.在我的电脑上,它导致死锁的概率为75%/

所以我们有2个线程:

线程_1正在创建A的实例

线程_2(主线程)正在创建B的实例

这是对类的首次访问,因此它可能导致并发类A和B的初始化.

下一步对我来说还不清楚.你能解释一下吗?

解决方案

  1. 否则,记录当前线程正在进行C的Class对象初始化的事实,然后释放LC.

因此,Thread_1开始初始化类A,并将其标记为由Thread_1初始化.类似地,类B被标记为由Thread_2初始化.

在第9步,调用静态初始化程序.

  1. 接下来,执行C的类或接口初始化方法.

A的静态初始化器创建B的实例,该实例尚未完全初始化,因此Thread_1(正在初始化A的过程中)递归地启动初始化B的过程. /p>

在该过程的第2步中,它检测到类B正在通过不同的线程和块进行初始化.

  1. 如果C的Class对象指示其他线程正在对C进行初始化,则释放LC并阻塞当前线程,直到得知正在进行的初始化已完成为止,然后重复此过程.
  2. li>

对称地Thread_2开始A的初始化,检测到它已经由不同的线程初始化,并在步骤2处阻塞.两个线程都被阻塞,等待彼此.

注意:该类被标记为完全初始化,并在成功调用静态初始化程序后 通知其他线程,在这种情况下永远不会发生.

  1. 如果类或接口初始化方法的执行正常完成,则获取LC,将C的Class对象标记为完全初始化,通知所有等待的线程,释放LC,然后正常完成此过程.

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

  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.

这篇关于类初始化死锁机制说明的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆