单例模式

Double Check Lock(DCL) (不推荐)

public class DCLSingleton {
    private static DCLSingleton sSingleton; // 存在风险
//    private volatile static DCLSingleton sSingleton;    // 避免风险
    private DCLSingleton() {
    }

    public DCLSingleton getInstance() {
        if (sSingleton == null) {
            synchronized (DCLSingleton.class) {
                if (sSingleton == null) {
                    sSingleton = new DCLSingleton();
                }
            }
        }
        return sSingleton;
    }
}

DCL失效问题
sSingleton = new DCLSingleton();看起来是一句代码,但实际上并不是一个院子操作,这句代码最终会被编译成多条汇编指令,大致做了3件事情:
(1)给Singleton的实例分配内存;
(2)调用Singleton()的构造函数,初始化成员变量;
(3)将sInstance对象指向分配的内存空间(此时sInstance就不是null了)。
由于Java编译器允许处理器乱序执行,(2)(3)执行顺序无法得到保证。如果在线程A执行1-3-2, 在3执行完了,2执行之前的时候,线程B调用getInstance,取走了一不为空,但没有实例化完成的instance,就会出错。这就是DCL失效问题。
使用volatile关键字可以保证sInstance每次都从主内存中读取,避免上述问题,但会牺牲一定的性能。

静态内部类单例模式(推荐)

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

参考
《Android源码设计模式解析与实战》

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容