热门搜索 :
考研考公
您的当前位置:首页正文

单例模式之懒汉式代码优化(双重检查)

来源:东饰资讯网

问题分析

/**
 * @Auther: ming.wang
 * @Date: 2019/1/6 19:25
 * @Description:
 */

public class LazySingleton {
    private static LazySingleton lazySingleton=null;
    private LazySingleton() {
    }

    public synchronized static LazySingleton getInstance(){
        if (null==lazySingleton)
        {
            lazySingleton=new LazySingleton();
        }
        return lazySingleton;
    }

}

但同时也有个小小的缺憾,就是synchronized关键字开销比较大。本篇文章就来分析改如何优化上述代码。

优化

其实优化思路已经在标题中体现了,就是使用双重检查的方式来减少进锁的几率。闲言碎语不要讲,直接上代码

/**
 * @Author: ming.wang
 * @Date: 2019/2/20 14:45
 * @Description:
 */
public class LazyDoubleCheckSingleton {

    private volatile static LazyDoubleCheckSingleton instance=null;

    private LazyDoubleCheckSingleton() {
    }

    public static LazyDoubleCheckSingleton getInstance(){
        if (null==instance) {//第一个 if(instance==null),其实是为了解决代码中的效率问题,只有instance为null的时候,才进入synchronized的代码段,大大减少了几率。
            synchronized (LazyDoubleCheckSingleton.class) {
                if (null==instance) {//第二个if(instance==null),则是为了防止可能出现多个实例的情况。
                    instance=new LazyDoubleCheckSingleton();
                    /*
                    * 1.分配内存给这对象
                    * 2.初始化对象
                    * 3.设置instance指向刚刚分配的内存空间(执行完这步 instance才是非 null了)
                    * 其中2和3会指令重排序,执行顺序可能为123或132
                    * */
                }
            }
        }
        return instance;
    }
}

上述代码有几处我们需要分析一下

  • i. 双重检查的含义
    代码中我们使用了两处if (null==instance)空判断。第一个 if(instance==null),其实是为了解决代码中的效率问题,只有instance为null的时候,才进入synchronized的代码段,大大减少了执行synchronized的几率。第二个if(instance==null),则是为了防止可能出现多个实例的情况。

volatile阻止的不是singleton = new Singleton()这句话内部[1-2-3]的指令重排,而是保证了在一个写操作([1-2-3])完成之前,不会调用读操作(if (instance == null))。

修订

在《java并发编程的艺术》一书中,明确说明了,此处使用volatile关键字修饰的作用就是限制指令重排序(保证时序为123)。

Top