线程绝对安全的单例模式

线程绝对安全下的单例模式

想要保证线程安全,基本的操作就是加锁,只让一个线程操作同享数据,其他线程进行等待,我们可以采用同步方法,同步代码块,等等,最受关注的DCL双重检查

class singleton {
    private singleton() {
    }
    private static singleton instance = null;

    public static singleton getInstance() {
        if (instance == null) {
            synchronized (singleton.class) {
                if (instance == null) {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    instance = new singleton();
                }

            }
        }
        return instance;
    }
}

双重检查是否真的一定绝对安全呢,答案是不一定
在这里插入图这片描述
通过这个加载的字节码文件我们可以看到

instance = new singleton();

这行代码他是调用空参构造器进行创建对象,也就是我们图片看到的init方法,创建一个对象的过程的最后一步才是初始化实例完成。看修改后的代码:

class singleton {
    private singleton() {
    }

    //2.如果在没有执行init方法前instance已经被创建,这时有一个线程进来判断instance并不为null
    //这时他直接将还没有初始化成功的instance实例返回出去,这就是指令重排问题。
    //3.避免指令重排,在声明instance变量是加上volatile关键字即可
    private static volatile singleton instance = null;

    public static singleton getInstance() {
        if (instance == null) {
            synchronized (singleton.class) {
                if (instance == null) {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    //1.创建对象的步骤其实分为很多步骤,而构造器的init方法是最后完成的。
                    instance = new singleton();
                }

            }
        }
        return instance;
    }
}

配合代码注释我相信你已经明白了DCL下的线程安全问题如果解决了​😄​​😄​

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值