为什么我们不要求同步 lazy-init getter(holder 惯用语)?
Why don't we require a lazy-init getter to be synchronized (the holder idiom)?
我正在阅读 J. Bloch 的 effective Java,现在我正在阅读有关惰性初始化的部分。考虑以下 class:
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
class 加载后才会创建 Object
的实例。 Holder
class 的加载将由 classloader 在您的应用程序中第一次引用字段 o
期间执行(这里是 getObject
方法)。类加载是非同步的,所以这个模式保证:
Object
实例将按需创建(惰性初始化)。
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.
我正在阅读 J. Bloch 的 effective Java,现在我正在阅读有关惰性初始化的部分。考虑以下 class:
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
class 加载后才会创建 Object
的实例。 Holder
class 的加载将由 classloader 在您的应用程序中第一次引用字段 o
期间执行(这里是 getObject
方法)。类加载是非同步的,所以这个模式保证:
Object
实例将按需创建(惰性初始化)。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.