gpt4 book ai didi

oop - 为什么我们同步懒惰的单例而不同步急切的单例?

转载 作者:行者123 更新时间:2023-12-04 21:56:32 27 4
gpt4 key购买 nike

典型的懒惰单例:

public class Singleton {
private static Singleton INSTANCE;

private Singleton() {

}

public static synchronized Singleton getInstace() {
if(INSTANCE == null)
INSTANCE = new Singleton();

return INSTANCE;
}
}

典型的急切单例:

public class Singleton {
private static Singleton INSTANCE = new Singleton();

public static Singleton getInstance() {
return INSTANCE;
}
}

为什么我们不关心与急切的单例的同步,却不得不担心与其懒惰的表兄弟的同步?

最佳答案

Eager 实例化不需要显式同步来共享字段的引用,因为 JVM 已经作为类加载机制的一部分为我们处理了它。

更详细地说,在一个类可供任何线程使用之前,它会被加载、验证和初始化。编译器将静态字段赋值重写到这个初始化阶段,并通过 Java 内存模型的规则和底层硬件架构将确保访问该类的所有线程都将看到该类的这个版本。这意味着 JVM 将为我们处理任何硬件障碍等。

也就是说,我建议将急切初始化标记为最终。这将使您的意图更加清晰,并且编译器将强制执行热切初始化永远不会改变。如果是,则将再次需要并发控制。

private static **final** Singleton INSTANCE = new Singleton();

仅供引用,如果您有兴趣,请参阅 Java Virtual Machine Specification 的第 5.5 节更详细地介绍了这一点。规范中的几个选择片段是

*"Because the Java Virtual Machine is multithreaded, 
initialization of a class or interface requires careful
synchronization"*

*"For each class or interface C, there is a unique initialization lock LC"*

*9&10) "Next, execute the class or interface initialization method of C"
"If the execution of the class or interface initialization
method completes normally, then acquire LC, label the Class object for
C as fully initialized, notify all waiting threads, release LC, and
complete this procedure normally."*

规范的第 10 步将设置静态字段,并使用锁 (LC) 确保只有一个线程执行初始化并正确共享结果。

关于oop - 为什么我们同步懒惰的单例而不同步急切的单例?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15178382/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com