Java单例双重检查问题

public class Singleton {
    private static Singleton singleton;
    public static Singleton getInstance(){
        if (singleton == null){
            synchronized (Singleton.class){
                if (singleton == null){
                    singleton = new Singleton();
                }
            }
        }
        return singleton;
    }
}
原因

在代码执行到singleton = new Singleton();时,这一步会分解成3个步骤:
1.分配内存空间
2.创建对象
3.singleton引用指向内存空间


依赖关系

由于2,3操作之间没有依赖关系,JAVA编译器可能会对其进行指令重排,此时会出现3->2情况,当一个线程进行3时,而2未初始化完成,则会出现异常。

解决办法

1.不允许2和3进行重排序
对singleton增加votatile关键字,保证只有一个线程获取singleton。
2.允许2和3重排序,但不允许其它线程"看到"这个重排序。
原理:JVM在类的初始化阶段(Class加载后且被线程使用前),会执行类的初始化。在执行类的初始化期间,JVM会去获取一个锁。这个锁可以同步多个线程对同一个类的初始化,基于这种特性,实现另一种线程安全的延迟初始化方案:

public class InstanceFactory {
    public static Instance getInstance(){
       return InstanceHolder.instance;
    }
    private static class InstanceHolder{
       public static Instance instance = new Instance();
    }
}

如果两个线程并发执行getInstance()方法:


并发执行示意图

执行的实质是:允许线程A中的2和3重排序,但不允许线程B"看到"这个重排序

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容