在我的应用程序中,有一个类如下:
public class Client {
public synchronized static print() {
System.out.println("hello");
}
static {
doSomething(); // which will take some time to complete
}
}
该类将用于多线程环境,多个线程可能同时调用Client.print()方法。请问有没有可能是thread-1触发类初始化,在类初始化完成前,thread-2进入print方法,打印出“hello”字符串?
我在生产系统(64 位 JVM + Windows 2008R2)中看到了这种行为,但是,我无法在任何环境中使用简单的程序重现这种行为。
在 Java 语言规范的第 12.4.1 节 (http://java.sun.com/docs/books/jls/second_edition/html/execution.doc.html) 中,它说:
A class or interface type T will be initialized immediately before the first occurrence of any one of the following:
- T is a class and an instance of T is created.
- T is a class and a static method declared by T is invoked.
- A static field declared by T is assigned.
- A static field declared by T is used and the reference to the field is not a compile-time constant (§15.28). References to compile-time constants must be resolved at compile time to a copy of the compile-time constant value, so uses of such a field never cause initialization.
根据这段,类初始化将在调用静态方法之前进行,但是,尚不清楚类初始化是否需要在调用静态方法之前完成 .根据我的直觉,JVM 应该在进入其静态方法之前强制完成类初始化,并且我的一些实验支持我的猜测。但是,我确实在另一个环境中看到了相反的行为。有人可以告诉我一些关于这个的信息吗?
感谢任何帮助,谢谢。
最佳答案
我对引用文本的理解是类初始化过程在调用 T 声明的静态方法之前完成(将初始化) em>.
will be initialized 表示初始化过程已经开始,已经终止。
因此(根据我的理解)应该不可能,因为线程 A 调用了 print
而执行了静态初始化程序,而另一个线程已经可以调用 print
。
Chapter 12.4.2 JLS 描述了详细的初始化过程,它负责在多线程环境中初始化类。
关于java - 类初始化和同步类方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4623484/