设计模式学习笔记

设计模式之单例模式

2020-11-27  本文已影响0人  小宋敲码

单例模式

重点

懒汉式单例类

在第一次被引用时,才会将自己实例化

class Singleton {
    private volatile static Singleton singleton;

    private Singleton() {
    }

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

注意:singleton的变量声明成 volatile。不加的话会有问题,主要在于singleton = new Singleton()这句,这并非是一个原子操作,事实上在 JVM 中这句话大概做了下面 3 件事情:
1.给 singleton 分配内存
2.调用 Singleton 的构造函数来初始化成员变量
3.将 singleton 对象指向分配的内存空间(执行完这步 singleton 就为非 null 了)。

但是在即时 JVM 的编译器中存在指令重排序的优化。也就是说上面的第二步和第三步的顺序是不能保证的,最终的执行顺序可能是 1-2-3 也可能是 1-3-2。如果是后者,则在 3 执行完毕、2 未执行之前,被线程二抢占了,这时 instance 已经是非 null 了(但却没有初始化),所以线程二会直接返回 instance,然后使用,然后顺理成章地报错。

使用volatile的主要原因是其有个特性:禁止指令重排序优化.也就是说,在volatile变量的赋值操作后面会有一个内存屏障(生成的汇编代码上),读操作不会重排序到内存屏障之前。 比如上面的例子,读操作必须要等到1-2-3或1-3-2执行完成,不存在1-3然后取值的情况。

饿汉式单例类

单例会在加载类后一开始就被初始化,即使客户端没有调用 getInstance()方法。

    //类加载时就初始化
    private static final Singleton singleton = new Singleton();

    private Singleton() {
    }

    public static Singleton getInstance() {
        return singleton;
    }

静态内部类 static nested class

class Singleton {
    private static class SingletonHolder {
        private static final Singleton INSTANCE = new Singleton();
    }

    private Singleton() {
    }

    public static final Singleton getInstance() {
        return SingletonHolder.INSTANCE;
    }
}

这种写法仍然使用JVM本身机制保证了线程安全。由于静态单例对象没有作为Singleton 的成员变量直接实例化,因此类加载时不会实例化Singleton,第一次调用getInstance()是将加载内部类SingletonHolder,在该内部类中定义了一个static类型的变量INSTANCE,此时会首先初始化这个成员变量,由JAVA虚拟机来保证其线程安全性,确保该成员变量只能被初始化一起。由于 getInstance() 方法没有任何线程锁定,因此其性能不会造成任何影响。
由于SingletonHolder 是私有的,除了 getInstance() 之外没有办法访问它,因此它是懒汉式的;
同时读取实例的时候不会进行同步,没有性能缺陷;
也不依赖JDK版本;

总结

一般情况下直接使用饿汉式就好了,如果明确要求要懒加载(lazy initialization)倾向于使用静态内部类。如果涉及到反序列化创建对象时会试着使用枚举的方式来实现单例。

参考:https://lrh1993.gitbooks.io/android_interview_guide/content/design-mode/Builder-Pattern/Singleton-Pattern.html

上一篇 下一篇

猜你喜欢

热点阅读