不同类的静态初始化器与构造函数间的数据竞争问题
问题解答
核心结论
根据JMM类初始化规则,当线程尝试读取类A的静态字段时,如果类A仍处于初始化过程中,该线程会被阻塞,直到类A的静态初始化完全完成后才能继续执行。因此可以保证读取到类A静态字段的最终初始化值。
针对你给出的示例代码,field_long不存在数据竞争,原因如下:
代码分析
- 类初始化的线程安全性:JVM会保证一个类的初始化过程是线程安全的——同一时间只有一个线程能执行类的初始化逻辑,其他尝试访问该类静态字段的线程会被阻塞,直到初始化完成。
- TextField的初始化顺序:
- 首先创建
FieldType实例,调用构造函数将field_long设为-1L; - 将该实例赋值给静态字段
TEXT_FIELD_TYPE; - 执行静态代码块,调用
set_field_long(1L)将field_long修改为1L; - 标记
TextField类初始化完成。
- 首先创建
- 线程访问时机:线程
t1和t2在访问TextField.TEXT_FIELD_TYPE时,无论哪个线程先触发TextField的初始化,另一个线程都会等待初始化完成后才能获取到TEXT_FIELD_TYPE的引用。因此所有线程拿到的FieldType实例,其field_long的值必然是静态代码块修改后的1L,不存在多线程下的不一致读取或竞争问题。
内容的提问来源于stack exchange,提问作者alex01011
相关产品推荐
相关产品推荐

