静态方法和静态块之间的线程安全性

时间:2017-05-21 12:55:51

标签: java multithreading static thread-safety

在多线程环境中,是否一个类的静态块保证在调用其他静态方法(在同一个类中)之前完成?

我不是指静态块本身调用其他静态方法的情况。为了澄清,我们可以使用以下代码块。

外部类可以启动两个线程,两个线程都调用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?
    }
}

1 个答案:

答案 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并正常完成。