现在常用的单例模式实现方式

来源:互联网 发布:淘宝卖电子书需要什么 编辑:程序博客网 时间:2024/06/06 21:03

我们在刚接触单例模式的时候相信大家都学习了常见的懒汉式和饿汉式,分析了利弊之后开始使用双重检查锁的方式。
其实双重检查锁并不能保证绝对的单例模式。至于为什么可以网上查一下,资料一大堆。今天我要说的是最优方案。静态内部类方式和volatile修饰的双重检查锁方式。

public class Singleton {private static class SingletonHolder {        public static final Singleton instance = new Singleton();    }    public static Singleton getInstance() {        return SingletonHolder.instance;    }}

原因分析:为什么静态内部类可以保证单例?
内部静态类是要在有引用了以后才会装载到内存的。所以在你第一次调用getInstance()之前,SingletonHolder是没有被装载进来的,只有在你第一次调用了getInstance()之后,里面涉及到了return SingletonHolder.instance; 产生了对SingletonHolder的引用,内部静态类的实例才会真正装载。这也就是懒加载的意思。
线程安全是因为,类加载的初始化阶段是单线程的(类加载是互斥的),类变量的赋值语句在编译生成字节码的时候写在函数中,初始化时单线程调用这个完成类变量的赋值。

volatile修饰的双重检查锁模式

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

原因分析:为什么双重检查锁不能保证绝对的单例,加上volatile之后就可以了呢?
volatile的作用:(JDK5)可以保证多线程下的可见性;
读volatile:每当子线程某一语句要用到volatile变量时,都会从主线程重新拷贝一份,这样就保证子线程的会跟主线程的一致。

写volatile: 每当子线程某一语句要写volatile变量时,都会在读完后同步到主线程去,这样就保证主线程的变量及时更新。

原创粉丝点击