深入探索单例之懒汉模式LazySingleTon

深入探索单例模式singleTon

单例模式:保证在任何类任何方法中,获取到某类实例只有一个

第一种方式
public class LazySingleTon {
    private  LazySingleTon singleTon;

    //私有化构造方法
    private LazySingleTon(){}

    //对外部提供一个方法,用于获取LazySingleTon实例
    public synchronized  LazySingleTon getInstance(){
        if(singleTon==null){
            return singleTon=new LazySingleTon();
        }
        return singleTon;
    };
}

分析:这种方式好吗? 对getInstance()加锁合适吗

  • 这种方法能保证实例只有一个,我们的目的达成了.但是考虑效率的话,这种方法怎么样?

  • 假设有多个线程调用getInstance()方法,获取LazySingleTon类的实例 . 但是由于该方法被synchronized修饰,一次只能有一个线程调用该方法,那么效率会很低 所以这种方法不推荐

  • 在想想getInstance()方法,仅仅只是一个获取实例的方法,我们保证单例确实跟该方法没多大关系… 重点在我们要保证new LazySingleTon()只能运行一次

第二种方式

在这里插入图片描述
当T1,T2进入图示位置,new LazySingleTon()会被执行两次.所以还需要改进 这里我们采用双重锁的方法

在这里插入图片描述

至此,我们第二种方式完成单例模式勉强算完成

那么为什么算勉强完成了呢? 我们来分析

我们在single=new LazySingleTon()时,过程可以细分为 1. 开辟内存空间 2. 初始化内存空间 3. 内存空间引用赋值给single

2,3步骤都是依赖1进行的,并且2,3步骤顺序是可以打乱的 .我们的cpu,编译器(JIT)对具有这种特征的过程可能进行了指令重排序,一旦进行了指令重排序<看下图>
在这里插入图片描述

那该怎么解决?

引入volatile关键字,使得singleTon=new LazySingleTon()这个过程不能被指令重排为多个步骤

public class LazySingleTon {
    private volatile LazySingleTon singleTon;

    //私有化构造方法
    private LazySingleTon(){}

    //对外部提供一个方法,用于获取LazySingleTon实例
    public  LazySingleTon getInstance(){

            if(singleTon==null){

                synchronized (LazySingleTon.class){

                    if(singleTon==null){
                        return singleTon=new LazySingleTon();
                        //1.开辟内存空间
                        //3.内存引用赋值给singleTon
                        //2.初始化内存空间
                    }

                }
            }
        return singleTon;
    };
}

}

            }
        }
    return singleTon;
};

}

至此,懒汉模式完美解决

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值