【问题标题】:bill pugh singleton, why thread safe?bill pugh 单例,为什么线程安全?
【发布时间】:2018-11-19 03:33:25
【问题描述】:

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

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
}

【问题讨论】:

  • 您的答案在 cmets 本身内
  • 因为加载和初始化类的语义被定义为只执行一次并且静态最终字段被安全发布。
  • Brian Goetz 最好地解释了这一点。你应该阅读他的书Java Concurrency in Practice 以获得完整的解释。对于精简版,请参阅这个 SO 问题:stackoverflow.com/questions/801993/…(但基本上,static 关键字在 Java 中是特殊的,并且由于 Java 类的加载方式和已初始化。)
  • @AndyTurner finalstatic 都可以。它是一个或另一个,它不需要是final。没有仔细检查,但我确定这是在 Brian Goetz 的书中。请再检查一遍!

标签: java multithreading singleton


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

    让我们来看看 cmets:

    // 静态内部类 - 内部类在被引用之前不会加载。

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

    “直到它们被引用” 表示在这种情况下,在 LoggerHolder.logger 静态字段被引用(“在某处使用”)之前,内部类(LoggerHolder)不会被初始化。

    所以对 getInstance() 的调用会引用 LoggerHolder.logger 并开始初始化 LoggerHolder 内部类。

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

    来自relevant documentation

    由于Java编程语言是多线程的,初始化 类或接口需要仔细同步

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

    静态字段的初始化:

    private static Logger logger = new Logger();
    

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-11-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多