2

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

它是一个单例类,它的实例变量不是易失的,即

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 会使信息从内存中读取,而不是从缓存中读取。

那么我应该让我的变量 volatile 吗?

如果不稳定,那么我是否必须一次又一次地加载我的数据?

4

2 回答 2

1

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

 public enum Server{
      INSTANCE;

      public Server getInstance(){
          return INSTANCE;
      }

      private Server(){...}

      // rest of methods here
 }

Singleton:枚举方式

于 2013-09-26T10:49:06.787 回答
0

是的 - 如果没有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时会发生类初始化,因此会被延迟实例化。getInstanceServer

于 2013-09-26T10:35:30.447 回答