【问题标题】:Volatile field in Singleton class in JavaJava中Singleton类中的可变字段
【发布时间】:2012-11-07 18:23:26
【问题描述】:

在一些网站/博客中,我发现单例代码为

public class MySingleton{

    private static MySingleton instance = null;
    .......
    .......
}

在其他一些地方,我发现单例代码为

public class MySingleton{

    private volatile static MySingleton instance = null;
    .......
    .......
}

是否有必要将MySingleton 引用为volatile?会有什么意义吗?

【问题讨论】:

标签: java singleton volatile


【解决方案1】:

Java 中的 Volatile 关键字用作 Java 编译器和线程的指示符,它们不缓存此变量的值并始终从主内存中读取它

** 编辑 **

private volatile static MySingleton instance = null;

在上面的代码 sn-p 中,volatile 关键字确保多个线程在将 instance 变量初始化为 MySingleton 实例时正确处理它。

阅读更多:http://javarevisited.blogspot.com/2011/06/volatile-keyword-java-example-tutorial.html#ixzz2BYyA5Jnm

【讨论】:

    【解决方案2】:

    嗯,是的,如果它是可变的并且出现在多线程代码中。您只需要了解volatile 的含义,单身人士是否需要使用它并没有什么特别之处。

    【讨论】:

    • 在多线程环境下,我们同步方法或者使用返回Singleton的同步块..那么volatile需要什么?
    • @djechlin 如果授予对该字段访问权限的 getter 使用同步形式,则不需要 volatile。
    【解决方案3】:

    无法判断 - 在两个示例中,字段都是私有的,因此根据它们的发布方式,您可能需要也可能不需要它们是易变的。标准的成语是to use an enum

    【讨论】:

      【解决方案4】:

      您想通过enum 保持简单

      public enum MySingleton {
          INSTANCE
      }
      

      或者你有充分的理由让它变得更复杂

      public class MySingleton {
          private MySingleton() { }
      
          private static MySingleton instance = null;
      
          public synchronized static MySingleton getInstance() {
               if (instance == null)
                   instance = new MySingleton();
               return instance;
          }
      }
      

      无论哪种方式,使用 volatile 都无济于事。

      恕我直言,没有一个好的 Singleton 模式可以让您使用volatile,所以如果需要,代码需要修复或简化。


      AFAIK 唯一使用 volatile 的情况是双重检查锁定

      public class MySingleton {
          private MySingleton() { }
      
          private static volatile MySingleton instance = null;
      
          public static MySingleton getInstance() {
               if (instance == null)
                   synchronzied(MySingleton.class) {
                       if (instance == null)
                           instance = new MySingleton();
                   }
               return instance;
          }
      }
      

      为了比较,上面的 enum 示例做了很多示例。

      http://javarevisited.blogspot.co.uk/2011/06/volatile-keyword-java-example-tutorial.html

      http://www.ibm.com/developerworks/java/library/j-dcl/index.html

      【讨论】:

      • "There's not a good pattern where you would use volatile" 可能有点强,除非你的意思是一个好的 singleton 模式。
      • @assylias 你是对的,但是在单例的许多模式中,AFAIK 只有双重检查锁定使用 volatile,虽然它不再是错误的,但它是不必要的复杂。
      • 我最初将其读作不使用 volatile(根本) - 当您的意思是在编写单例时不要使用 volatile。 ;-)
      • @assylias volatile 有一些用途,但在大多数 Singleton 模式中没有。 (例如停止线程的标志应该是volatile
      【解决方案5】:

      只有在多线程系统中有一个可变单例字段时才需要这样做,尤其是在单例被延迟初始化的情况下。

      这是关于如何在 Java 中的多线程系统中延迟初始化单例的大型讨论的一部分。有几种机制可用于此目的,但最流行的是:

      目前公认的为多线程系统保存延迟初始化的单例的方法是 enum 方法,尽管它们都在 Java 1.5+ 中工作。

      【讨论】:

      • 延迟初始化?你能引用吗?大多数 IDE 的单例模板都使用 holder 成语。
      • 在加载枚举类之前,不会初始化单例。例如:stackoverflow.com/a/7790749/829571 或这个:stackoverflow.com/a/3635619/829571
      • 很公平,我只有一个担心。 public static 变量或方法,独立于单例的初始化,在单例的类中呢?当访问枚举的静态方法或字段时,将加载实例,而持有者惯用语不会发生这种情况,它在调用getInstance 时初始化。它们必须被重构为一个单独的类(这不一定是坏事)。除此之外,我绝对明白你的意思,我会更新我的答案并将这个模式添加到我的工具带中,谢谢:)
      猜你喜欢
      • 2016-09-06
      • 1970-01-01
      • 1970-01-01
      • 2015-01-21
      • 1970-01-01
      • 2015-10-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多