繁体   English   中英

Singleton类及其实例为volatile是否会使实例数据再次被加载?

[英]Does Singleton class with its instance as volatile make the instance data to be load again?

在我的应用程序中,服务器类是在启动时加载的,所有数据都被缓存一次。

这是一个单例类,其实例变量不是volatile,即

private static Server server;

经过findbug分析后,我必须将其更改为volatile,(如下所示

public class Server {
    private static volatile Server server;

    public static Server getInstance(){
        if(server == null){
            synchronized (Server .class) {
                if(server == null){
                    try {
                        server = new Server(....);
                    } catch (IOException e) {
                        Logger.logError(MODULE, "IO Error while creating server home location: " + strServerHome);
                        Logger.logTrace(MODULE, e);
                    }
                }
            }
        }
        return server;
    }.......
}

但是在阅读了有关堆栈上的volatile的文章和Q / A之后,我认为volatile将使数据再次加载,因为volatile使信息从内存中读取而不是缓存。

那么我应该使变量可变吗?

如果易失,那么我是否必须一次又一次地加载数据?

创建线程安全的单例通常被认为最安全的方法是使它成为枚举。

 public enum Server{
      INSTANCE;

      public Server getInstance(){
          return INSTANCE;
      }

      private Server(){...}

      // rest of methods here
 }

辛格尔顿:枚举方式

是的-在没有volatile ,您拥有臭名昭著的“双重检查锁定”反模式,它不是线程安全的(即使看起来如此)。 (即使使用volatile,使用Java 5之前的Java版本也不是线程安全的)。

http://en.wikipedia.org/wiki/Double-checked_locking#Usage_in_Java

但是,尽管它的线程安全且使用volatile并且Java> = 5,但它的代码很丑,所以您应该编写一个简单的synchronized getInstance方法...

public static synchronized Server getInstance() {
    if (server == null) server = new Servier(...);
    return server;
}

...或使用按需持有人模式的初始化程序:

private static class ServerHolder {
    public static Server server = new Server(...);
}

public static Server getInstance() {
    return ServerHolder.server;
}

因为ServerHolder类是在第一次使用时延迟加载的,所以在首次调用getInstance时将发生类初始化,因此Server将被延迟实例化。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM