java单例与双重检查

标签 java singleton

众所周知,简单的双重检查由于 JVM 的命令调用而存在问题。

class MyClass {

    private String Name;

    private static Object o = new Object();
    private static MyClass Instance=null;

    private MyClass(){
        //Thread.sleep(1000);
        Name="test case";
    }
    public static MyClass GetInstance(){
        if(Instance==null){
            synchronized(o){
                if(Instance==null){
                    Instance = new MyClass();
                    //MyClass obj = new MyClass();
                    //Instance = obj;
                }
            }
        }
        return Instance;
    }
}

如果我将 Instance = new MyClass(); 替换为注释行。这有效吗?

最佳答案

不,这不起作用。考虑线程A和B;线程 A 看到 Instancenull 并进入同步块(synchronized block)创建 MyClass 的实例并将其分配给字段 Instance.

由于Java内存模型的规则,可能会发生重新排序,并且MyClass的部分初始化甚至未初始化的对象可以被分配给Instance。现在,线程 B 进入相同的 GetInstance 方法,并发现 Instance 不为 null,永远不会在与线程 A 相同的监视器上进入同步块(synchronized block),然后返回一个对象,该对象为未完全初始化。

是否将初始化拆分为两行代码或将其保留在一行上对于此问题绝对没有意义:在任何一种情况下都可能发生重新排序。 Java 编译器可以合法地将代码的两个版本编译为相同的字节码(尽管当前的编译器不会)

关于java单例与双重检查,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36490101/

相关文章:

singleton - casTLe 如何解析单例对象?

java - 如何将 OpenOffice.org 作为后台进程运行以连接我的应用程序以使用 UNO Java API?

java - 字符串格式查询

java - 如何使用单例模式计数器为图像上传设置自动数字名称生成器

c++ - 在线程中从 C++ 调用 Lua

c# - 我们应该密封单例吗?我们应该首先尝试继承单例吗?

java - 使用 GWT RequestBuilder 的 YouTube GetUploadToken 请求后状态 404

java - JDBC + JSF,出现错误 : Parameter index out of range (2 > number of parameters,,即 1)

java - NoSql 之战——幸存者?

c# - 配置 DI 后 ASP.NET Core 初始化单例