双重检查单例

单例模式是java开发模式最常用的一种。 今天深入学习双重检查单例。

先看几种典型单例代码:

 private Sington(){

    }
    //  方案1
    // 最简单单例,final 保证只能new一下
    // 不能接受启动就创建对象。万一不用不就浪费了?
    private static final Sington instans0=new Sington();
    public static Sington instance0(){
        return instans0;
    }
    //  方案2
    // 方法加锁,进阶懒加载
    // 锁住了整个方法, 每次调用都lock一下也不能接受
    private static Sington instans1=null;
    public synchronized static Sington instance(){
        if(instans1==null){ 
            instans1=new Sington();
        }
        return instans1;
    }
    //  方案2 类似
    private static Sington instans2=null;
    public  static Sington instance2(){
        synchronized(Sington.class){
            if(instans2==null){
                instans2=new Sington();
            }
        }
        return instans2;
    }
    // 方案3:双重检查单例
    // 懒加载
    // 上来无脑加锁不能接受,增加null判断。 
    // 问题又来了:为啥要用volatile???
    private static volatile Sington instans3=null;
    public  static Sington instance3(){
        if(instans3==null){ 
            synchronized(Sington.class){
                if(instans3==null){
                    instans3=new Sington();
                }
            }
        }
        return instans3;
    }


    //补充 早期使用内部静态类实现的线程安全且懒汉加载的方式
    public static Sington getInstance4() {
        return SingletonHolder.INSTANCE;
    }

    private static class SingletonHolder {

        private static final Sington INSTANCE = new Sington();
    }

重点来了:volatile 存在的意义是什么?

这里涉及了好几个知识点 ,指令重排,内存屏障,类实例化过程。

volatile 有什么特性?

  1. 线程可见
  2. 禁止指令重排序

什么是指令重排?

这里不深入解释,简单来说,在多线程环境下,cpu指令为了提升性能,对于没有绝对先后顺序的指令存在乱序执行的可能性。 

了解类的实例化

类实例化主要3个步骤实例化->初始化->返回。  在实例化过程中存在初始化还没执行,已经返回了。 

线程2拿到未初始化的实例对象, 后续时候就会报错。 

补充内部静态类的单例实现方法

使用内部静态类这是一种简单有效的方法,但这个final存在的意义是什么?

根据我的理解,Sington虽然定义静态常量字段(基本类型与String是才直接虚拟机初始化),但初始化jvm把它是放在cinit方法里面。jvm保证cinit方法有且执行一次,理论上加final与不加final并无差别。

根据测试结果final加还是不加都没有出现多个单例对象的情况。不知道有没有过客可以解释一下这个final存在的意义。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值