类初始化死锁机制说明 [英] Class initialization deadlock mechanism explanation
问题描述
我找到了文章( 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的初始化.
下一步对我来说还不清楚.你能解释一下吗?
- 否则,记录当前线程正在进行C的Class对象初始化的事实,然后释放LC.
因此,Thread_1
开始初始化类A
,并将其标记为由Thread_1
初始化.类似地,类B
被标记为由Thread_2
初始化.
在第9步,调用静态初始化程序.
- 接下来,执行C的类或接口初始化方法.
A
的静态初始化器创建B
的实例,该实例尚未完全初始化,因此Thread_1
(正在初始化A
的过程中)递归地启动初始化B
的过程. /p>
在该过程的第2步中,它检测到类B
正在通过不同的线程和块进行初始化.
- 如果C的Class对象指示其他线程正在对C进行初始化,则释放LC并阻塞当前线程,直到得知正在进行的初始化已完成为止,然后重复此过程.
li>
对称地Thread_2
开始A
的初始化,检测到它已经由不同的线程初始化,并在步骤2处阻塞.两个线程都被阻塞,等待彼此.
注意:该类被标记为完全初始化,并在成功调用静态初始化程序后 通知其他线程,在这种情况下永远不会发生.
- 如果类或接口初始化方法的执行正常完成,则获取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".
- 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.
这篇关于类初始化死锁机制说明的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!