比尔皮尤单例,为什么线程安全?

2022-09-04 22:59:19

为什么Bill Pugh的单例设计模式线程是安全的?

public class Logger {
    private Logger() {
        // private constructor
    }

    // static inner class - inner classes are not loaded until they are
    // referenced.
    private static class LoggerHolder {
        private static Logger logger = new Logger();
    }

    // global access point
    public static Logger getInstance() {
        return LoggerHolder.logger;
    }

    //Other methods
}

答案 1

让我们来看看评论:

静态内部类 - 在引用内部类之前,不会加载它们。

“加载”初始化内部类(LoggerHolder)的过程。

“直到它们被引用”意味着内部类(LoggerHolder)在引用LoggerHolder.logger静态字段(“在某处使用”)之前不会初始化。

因此,对 getInstance() 的调用引用了 LoggerHolder.logger 并启动了 LoggerHolder 内部类的初始化。

初始化类的整个过程由 JVM 同步

相关文档

因为 Java 编程语言是多线程的,所以类或接口的初始化需要仔细的同步

Java 虚拟机的实现负责处理同步和递归初始化

静态字段的初始化:

private static Logger logger = new Logger();

是内部类初始化的一部分,整个初始化过程(“加载”)由 JVM 有效地同步。


答案 2

我认为由于java中“静态”的定义,内部类和内部对象(在本例中为记录器)通过jvm与类加载器加载一次。

我认为最好将记录器对象定义为最终对象。第二个或其他线程无法再次实例化对象!


推荐