【详解】多线程下的单例模式

多线程下单例模式的问题

  • 多线程情况懒加载的单例模式,会导致多个线程同时加载对象
  • 此时可以采用二次检测的机制,实现对于性能以及安全的保障
  • 使用volatile关键字,可以保证可见性以及避免了各种优化造成的空指针问题,防止初始化实例写数据还没有完成,造成此时读数据的不准去

解决一:二次检测解决

public class SingletonObject2 {
    private static volatile SingletonObject2 instance ;

    private SingletonObject2(){
        //empty
    }

    public static SingletonObject2 getInstance(){
        if (null == instance){//两次检测的方式实现多线程情况下的懒加载
            synchronized (SingletonObject2.class){
                if (null == instance) {
                    instance = new SingletonObject2();
                }
            }
        }
        return SingletonObject2.instance;
    }
}

注意如果不加volatile关键字,可能会出现空指针异常

原因

  • 如果实例化SingletonObject2时,在构造方法中可能需要构造其他的实例,如Obj1,Obj2
  • JVM创建的顺序可能是:
  • Obj1 -> Obj2 -> SingletonObject2

  • 但是如果不加volatile关键字,可能会出现重排序,出现:
  • SingletonObject2->Obj1 ->Obj2

解决二:优雅的方式:Holder

  • 利用static类,将加载实例的方式放在类的属性中
  • 类加载器在没有使用到该类的时候,类里面的属性并没有被加载,保证了懒加载
  • static的特性可以保证JVM创建该属性的时候只会存在一个,保证了单例
  • 由于没有加锁,所以性能也可以保证
public class SingletonObject2 {

    private SingletonObject2(){
        //empty
    }


    private static class InstanceHolder{
        private final static SingletonObject2 instance = new SingletonObject2();
    }


    public static SingletonObject2 getInstance(){
        return InstanceHolder.instance;
    }
}

解决三:优雅的方式:枚举类型

  • 枚举类型的构造函数只会调用一次,保证了其单例的特性
public class SingletonObject2 {

    private SingletonObject2(){
        //empty
    }


    private enum Singleton{
        INSTANCE;

        private final SingletonObject2 instance;

        Singleton(){
            instance = new SingletonObject2();
        }
        public SingletonObject2 getInstance(){
            return instance;
        }
    }

    public static SingletonObject2 getInstance(){
        return Singleton.INSTANCE.getInstance();
    }


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值