线程安全的单例模式

线程安全的单例模式

饿汉式:类加载就会导致该实例对象被创建

懒汉式:类加载不会导致该实例对象被创建,而是首次使用该对象时才会被创建

饿汉式实现1:

//final为了防止子类继承,覆盖方法,从而破坏单例模式
public final class Singleton implements Serializable{
    //虽然是私有,但是还能通过反射来破坏单例对象
    private Singleton(){}
    //静态成员变量的初始化是在类加载阶段初始化,由jvm保障线程安全
    private static final Singleton INSTANCE = new Singleton();
    
    public static Singleton getInstance(){
        return INSTANCE;
    }
    //如果实现了Serializable接口,可以通过反序列化来创建新的对象
    //防止反序列破坏单例
    //反序列化时候,要是发现了readResovle方法,会返回方法中返回的对象
    public Object readResovle(){
        return INSTANCE;
    }
    
}

枚举实现2(饿汉):

//反射不能破坏,反射在通过newInstance创建对象时,会检查该类是否被ENUM修饰,如果是抛出异常
//虽然枚举类都实现了Serializable接口,但是父类的反序列化是通过valueOf实现的,所有不会破坏单例
//
enum Singleton{
	INSTANCE; 
}

懒汉实现3:

public final class Singleton{
    
    private Singleton(){}
    
    priavte static Singleton INSTANCE = null;
    //每次访问方法都需要加锁,性能会低
    public static synchronized Singleton getInstance(){
        if(INSTANCE!=null){
            return INSTANCE;
        }
        INSTANCE = new SINgleton();
        return INSTANCE;
    }
    
}

double-check-lock实现4:

对实现3的改进

public final class Singleton{
    private Singleton(){}
    //加入volatile,防止指令重排序
    private static volatile Singleton INSTANCE = null;
    
    public static Singleton getInstance(){
         //只有第一次创建对象的时候才需要加锁,性能比实现3高
        if(INSTANCE!=null){
            return INSTANCE;
        }
        synchronized(Singleton.class){
            //首次创建对象的时候,可能会有多个线程进行这一步,所以要加判断
            if(INSTANCE!=null){
            	return INSTANCE;
            }
            INSTANCE = new Singleton();
            return INSTANCE;
        }
    }
}

在这里插入图片描述

​ 本来应该是先用引用来调用构造方法,然后再将引用赋给INSTANCE,但是由于发生了指令重排,可能会先将引用赋给INSTANCE,然后再调用构造方法,当INSTANCE拿到引用后,如果此时有另一个线程执行了getInstance()方法,此时会进入第一个 if(INSTANCE!=null) 并返回INSTANCEINSTANCE只是一个引用而没有调用构造方法。

实现5(懒汉式):

public final class Singleton{
    private Singleton(){}
    
    //静态内部类,类加载是懒惰的,第一次使用的时候才会被加载,在类加载的阶段进行创建对象,有jvm保障其线程安全
    private static class LazyHolder{
        static final Singleton INSTANCE = new Singleton();
    }
    
    public static Singleton getInstance(){
        return LazyHolder.INSTANCE;
    }
    
}

推荐

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值