具有内部类的 Java Singleton - 什么保证线程安全?

标签 java multithreading

实现单例的一种常见(12)方法是使用带有静态成员的内部类:

public class Singleton  {    
    private static class SingletonHolder {    
        public static final Singleton instance = new Singleton();
    }    

    public static Singleton getInstance() {    
        return SingletonHolder.instance;    
    }

    private Singleton() {
        //...
    }
}

据说这个实现是延迟初始化和线程安全的。但是到底是什么保证了它的线程安全呢? JLS 17处理线程和锁 的文章没有提到静态字段具有任何类型的happens-before 关系。我如何确定初始化只会发生一次并且所有线程都看到相同的实例?

最佳答案

它在 Java Concurrency in Practice 中有详细描述:

The lazy initialization holder class idiom uses a class whose only purpose is to initialize the Resource. The JVM defers initializing the ResourceHolder class until it is actually used [JLS 12.4.1], and because the Resource is initialized with a static initializer, no additional synchronization is needed. The first call to getresource by any thread causes ResourceHolder to be loaded and initialized, at which time the initialization of the Resource happens through the static initializer.

静态初始化

Static initializers are run by the JVM at class initialization time, after class loading but before the class is used by any thread. Because the JVM acquires a lock during initialization [JLS 12.4.2] and this lock is acquired by each thread at least once to ensure that the class has been loaded, memory writes made during static initialization are automatically visible to all threads. Thus statically initialized objects require no explicit synchronization either during construction or when being referenced.

关于具有内部类的 Java Singleton - 什么保证线程安全?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46542017/

相关文章:

java - 如何在 Future.cancel 之后取消生成的 Callable?

c++ - boost::wait 和 boost::condition 是否必须共享相同的互斥对象

c# - 这是 async-await 工作原理的正确图表吗?

java - 如何在 Jersey 服务中返回特定响应

java - httpBasic() 和authorizeRequest() 之间的区别

计算超线程机器中的进程利用率

java - 如何使用Java在多线程中复制文件

java - 将正则表达式与replaceAll一起使用

java - 为什么我的两个线程可以通过非 volatile 字段进行协调?

java - 为什么用maven在Intellij中构建后总是缺少文件?