六大单例模式

单例模式,只能出现一个该类的实例对象。所以需要把构造方法访问类型改成private私有的。

饿汉式

通过static生产唯一的一个类变量成员

public class Main {
    private static Main instance=new Main(); 
    private Main(){}
    public static Main getInstance(){return instance;}
}

老板是个极其小气的人,走过来说,我都还没用这个类,你类加载就直接把instatnce初始化了,不行,内存不要钱啊

懒汉式

public class Main {
    private static Main instance;
    private Main(){}
    public static Main getInstance(){
        if (instance==null)
            instance=new Main();
        return instance;}
}

老板,好了,这样就不占你内存了,只有调用getInstance才会开始初始化。老板又不乐意了,你这多线程环境下直接就死翘翘了

synchronized

public class Main {
    private static Main instance;
    private Main(){}
    public static synchronized Main getInstance(){
        if (instance==null)
            instance=new Main();
        //其他业务方法
        //............
        //............
        return instance;}
}

不就是加把锁吗。好了。老板还是不通过,说为了一行初始化代码把其他业务全给阻塞了。

细粒度更小的synchronized(错误)

public class Main {
    private static Main instance;
    private Main(){}
    public static  Main getInstance(){
        if (instance==null)
            synchronized (Main.class){
                instance=new Main();
            }
        //其他业务方法
        //............
        //............
        return instance;}
}

老板这总可以了吧,老板被气傻了:你仔细看看这是线程安全的吗!
两个线程同时通过 if (instance==null)的判断,其中一个拿到锁进去初始化,另一个等待锁,初始化完毕后,第二个拿到锁,!他又初始化了一遍。老板马上改!

双重检查

public class Main {
    private static Main instance;
    private Main(){}
    public static  Main getInstance(){
        if (instance==null)
            synchronized (Main.class){
            if (instance==null)
                instance=new Main();
            }
        //其他业务方法
        //............
        //............
        return instance;}
}

我再加一个if不就行了,真的是。老板看着代码直摇头,下班后去人事部结工资吧。只见老板在instance前加了一个volatile关键字。

volatile双重检查

public class Main {
    private static volatile Main instance;
    private Main(){}
    public static  Main getInstance(){
        if (instance==null)
            synchronized (Main.class){
            if (instance==null)
                instance=new Main();
            }
        //其他业务方法
        //............
        //............
        return instance;}
}

instance=new Main();分为三部
1:申请内存
2:成员变量初始化
3:内存地址赋值给instance
这三部并不是按照顺序来执行的!!!!第二步和第三步调用顺序执行结果还是一样,所以它很有可能会被优化,申请完内存就直接赋值了,再去初始化成员变量。比如一个线程现在申请完内存,内存地址赋值给instance就在这时,又来了一个线程,他通过第一个if判断发现instance不为null了,直接把他返回!直接把一个未给成员变量初始化的对象返回了!难怪老板要开我。
而加了volatile之后,通过内存屏障禁止了指令重排,没了指令重排自然就安全了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值