设计模式学习---单例模式(双重检测锁以及volatile的必要性分析

引言

在学习创建型模式中的单例模式的时候,我们都会接触到双重检测锁实现的单例模式(饱汉模式),代码如下:

ublic class Singleton {
    /**
     * 饱汉模式(双重检测锁)
     */
    private Singleton(){};
    private static volatile Singleton instance = null;

    public static Singleton getInstance(){
        if(instance==null){
            synchronized (Singleton.class){
                if(instance==null){
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

可是为什么要使用volatile以及为什么要检测两次instance呢?

为什么使用Volatile

我们不妨先说一下volatile的作用

  • 防止指令重排
  • 指明被修饰的变量是不安全的,每次都必须到内存中读取

在单例模式中,我们使用volatile是为了防止指令重排,想象一下这种情况:当实例还没有创建的时候,线程A获得了synchronized锁,创建对象,虽然synchronized锁保证了操作的原子性,但是没有保证指令重排的正确性,如果构造函数中的操作很多,这个时候就可能出现instance已经被赋值了,但是还没有实例化完,这个时候如果线程B进入了,判断(instance==null)的时候就会误以为instance存在,直接返回,造成错误。

为什么要校验两次

想象一下这种情况:有两个线程同时通过了第一次判断instance==null,假设线程B获得了锁,此时线程A就处于等待状态。当线程B创建完实例之后,线程A可以获得这把锁,如果在这里没有第二次判断的话,线程A也会创建一个实例,这明显就与单例模式的初衷不符。

以上是我的个人理解。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容