【问题标题】:What makes initializing an object reference from a static initializer to publish the object safely?是什么使从静态初始化程序初始化对象引用以安全地发布对象?
【发布时间】:2012-07-03 10:19:01
【问题描述】:

考虑以下代码:

   // This code safely publishes the Publishable object
   public static Publishable publishable= new Publishable();

我见过这样一种发布自定义 Publishable 对象的方式,并且我读到这是安全的。我的问题是:

  1. 这是一种真的安全发布方式吗?
  2. 如果 1 的答案是否定的,那为什么?如果是,还请解释原因?

【问题讨论】:

    标签: java multithreading synchronization thread-safety


    【解决方案1】:

    根据 JCiP:

    静态初始化器在类初始化时由 JVM 执行 [...] 这种机制可以保证安全地发布以这种方式初始化的任何对象。

    参考:JLS 12.4.2 - 项目 9:

    接下来,按照文本顺序执行类的类变量初始化程序和静态初始化程序,或者接口的字段初始化程序,就好像它们是一个单独的块一样。

    【讨论】:

    • +1 值得将publishable 确定为最终版本,以确保它没有改变。
    • @PeterLawrey 尽管我明白你的意思,但这对于安全发布本身来说并不是必需的。
    • @assylias “类初始化”是指“类加载”吗?
    • @Subhra 类加载可以在没有初始化的情况下执行,但通常假设两者是一起的。
    【解决方案2】:

    从静态块运行或静态初始化的所有代码都是线程安全的。

    如果可以的话,我会让这个领域成为最终的。

     public static final Publishable publishable= new Publishable();
    

    甚至将 Publishable 设为枚举

     public enum Publishable {
          INSTANCE;
    
     }
    

    【讨论】:

    • 您说“所有代码从静态块运行或静态初始化都是线程安全的”。但我的问题是为什么它是线程安全的?
    • 查看 assylias 对标准的回答。你想知道为什么它是这样定义的吗?
    • @Subhra:只需在提供的 assylias 打开链接 - 第一段 :-)
    • @Peter +1 引入了枚举结构,这是发布单例的最佳方式。
    • @Subhra 有时最简单的解决方案也是最好的。 ;)
    【解决方案3】:

    我不认为这是一种特别好的初始化这个对象的方法(撇开“安全”这个词,我可以用多种方式解释)。

    它正在创建一个绑定到包含类的单例,并且初始化不受控制。或者更确切地说,它在加载该类时立即初始化。你对此有完全的控制权吗?

    我宁愿:

    1. 不使用单例。有关使用单例的困难的更多详细信息,请参阅here。我注意到您的问题被标记为与线程相关的关键字,并且单身人士会创建自己的线程问题。
    2. 让客户端类控制这个对象的初始化。您可能希望推迟该对象的初始化(想象一下,如果它突然变成一个重量级对象,在构造时执行网络调用等)。目前,上述内容对此提供的控制很少。

    【讨论】:

    • 虽然我同意你的主要观点,但如果相当明确的话,我认为多线程上下文中的“安全发布”。
    • @Brian +1 提到延迟初始化
    猜你喜欢
    • 2013-06-27
    • 1970-01-01
    • 1970-01-01
    • 2017-09-20
    • 2011-02-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多