在多线程环境中,是否一个类的静态块保证在调用其他静态方法(在同一个类中)之前完成?
我不是指静态块本身调用其他静态方法的情况。为了澄清,我们可以使用以下代码块。
外部类可以启动两个线程,两个线程都调用OurClass.doSomething()
,还有一个线程会在静态块完成之前开始执行吗?
public class OurClass {
static {
// does something that takes a long time
}
public static void doSomething() {
// can I be called before the block has finished?
}
}
答案 0 :(得分:3)
外部类可以启动两个线程,两个线程都调用 OurClass.doSomething(),其中一个将在之前开始执行 静态块完成?
不,这在Java的兼容实现中是不可能的。
请参阅section 12.4.1 of the Java Language Specification:
一个类或接口类型T 将在紧接之前初始化 首次出现以下任何一种情况:
T是一个类,并创建了一个T实例。
调用T声明的静态方法。
分配由T声明的静态字段。
使用T声明的静态字段,该字段不是常量变量(§4.12.4)。
T是顶级类(§7.6),并且执行词汇嵌套在T(§8.1.3)中的断言语句(§14.10)。
而section 12.4 just above this text描述了“初始化类类型T”意味着什么:
类的初始化由执行其静态组成 初始化器和静态字段的初始化器(类变量) 在课堂上宣布。
有关类初始化的多线程/内存模型含义的更多详细信息,需要阅读第12.4.2节(“12.4.2. Detailed Initialization Procedure")。
总之,本节解释了,只要Java想要使用特定的C类,它就需要行动*就好像它在该类C *上获得同步锁 LC 。
然后需要检查该类是否已经初始化。当类完全初始化时,它可能只对该类进行任何操作。如果它尚未初始化,并且它没有被另一个线程初始化,那么它需要在此时初始化类。
特别是对于您的评论,第12.4.2节规定,一旦在类上具有此同步锁定:
如果C的Class对象表示正在进行初始化 对于当前线程的C,那么这必须是递归请求 初始化。释放LC并正常完成。