当前位置: 首页 > 知识库问答 >
问题:

实例为volatile的Singleton类是否会再次加载实例数据?

马淳
2023-03-14

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

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

private static Server server;

在findbug分析后,我必须将其更改为易失性,(如下所示

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

那么我应该让我的变量不稳定吗?

如果不稳定,那么我必须再次加载我的数据

共有2个答案

澹台逸明
2023-03-14

是的-如果没有易失性,您就会得到臭名昭著的双重检查锁定反模式,它不是线程安全的(即使看起来是这样)。(即使使用易失性,Java5之前的Java版本也不会是线程安全的)。

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

但是,尽管它在volatile和Java中是线程安全

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将延迟实例化。

赫连泰宁
2023-03-14

通常认为创建线程安全的单例最安全的方法是将其设置为枚举。。。

 public enum Server{
      INSTANCE;

      public Server getInstance(){
          return INSTANCE;
      }

      private Server(){...}

      // rest of methods here
 }

单件:Enum方式

 类似资料:
  • 问题内容: 我已经找到了实例化Singleton的三种方法,但是我怀疑其中是否有最好的方法。我在多线程环境中使用它们,并且更喜欢延迟实例化。 范例1: 范例2: 范例3: 我正在使用ATM的项目到处都使用Sample 2,但我还是更喜欢Sample 3。还有Enum版本,但是我不明白。 这里的问题是- 在什么情况下我应该/不应该使用这些变体中的任何一个?我并不是在寻找冗长的解释(对此还有很多其他话

  • 问题内容: 我的代码中需要一个单例。我用Java实现了它,并且效果很好。我这样做的原因是为了确保在多种环境中只有一个此类的实例。 但是现在我想用单元测试在本地测试我的Singleton对象。因此,我需要模拟此Singleton的另一个实例(该对象可能来自另一个设备)。那么是否有可能第二次实例化Singleton以进行测试,还是我必须对其进行模拟? 我不确定,但是我认为可以通过使用其他类加载器来实现

  • 对于这个示例: null 是否有类似这样的语句用于此检查?或者我应该使用

  • 问题内容: 有没有办法确定对象是否是泛型类型的实例? 这显然行不通。还有其他选择吗?就像我想使用Java反射来实例化一个类,然后检查以确保它是通用类型。 问题答案: 进行此检查的唯一方法是,是否具有表示类型的对象:

  • Selenium FindBy注释是否实际实例化了WebElement实例,如果是,使用它们的框架的内涵是什么? 我在我的页面对象中所做的事情现在看起来是这样的。我的所有测试框架方法都将定位器作为参数(而不是WebElement实例)。 我的问题是,在类实例化时使用FindBy实例化WebElement实例吗?如果是这样,那么我怀疑我的框架方法需要使用WebElement实例。这是正确的吗,在框架

  • [dcl.spec.auto]/14国[强调我的]: 显式实例化声明不会导致使用占位符类型声明的实体的实例化,但也不会阻止根据需要对该实体进行实例化以确定其类型。[示例: -结束示例] 和[temp.explicat]/11声明[强调我的]: 现在,考虑我们是否在类模板中的friend声明中定义了friend函数: 如果在同一翻译单元中实例化了的多个专门化,则将违反[basic.def.odr]/