我正在阅读 J. Bloch 的《Effective Java》,现在正在阅读有关延迟初始化的部分。考虑下面的类:
public class LazyInit{
public static getObject(){ //Not synchronized
return Holder.o;
}
private static Object createObject(){
System.out.println("Creating started");
return new Object();
}
private static class Holder{
private static Object o = createObject();
}
}
J.布洛赫谈到这个习语时说:
The beauty of this idiom is that the getField method is not synchronized and performs only a field access, so lazy initialization adds practically nothing to the cost of access.
我不明白为什么它可以安全通过。如果在字段初始化期间另一个线程尝试同时访问该字段怎么办?该对象在线程需要它时尚未创建。那么,会发生什么?
最佳答案
这种方法基于JVM的初始化原理。
只有在加载Holder
类后才会创建Object
的实例。 Holder
类的加载将由类加载器在应用程序中第一次引用字段 o
时执行(这里是 getObject
方法)。类加载是非并发的,因此此模式保证:
Object
实例将根据需要创建(延迟初始化)。对象
的创建将是线程安全的。
取自 wiki article :
Since the class initialization phase is guaranteed by the JLS to be serial, i.e., non-concurrent, no further synchronization is required in the static getInstance method during loading and initialization.
评论更新:
@St.Antario 发现 formal JLS explanation对于此功能:
The procedure for initializing C is then as follows: Synchronize on the initialization lock, LC, for C. This involves waiting until the current thread can acquire LC.
关于java - 为什么我们不需要一个惰性初始化 getter 来同步(持有者习惯用法)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33773124/