码迷,mamicode.com
首页 > 其他好文 > 详细

单例模式

时间:2018-10-08 10:22:36      阅读:198      评论:0      收藏:0      [点我收藏+]

标签:机制   on()   zed   延迟加载   基础   初始   多线程   volatil   检测   

目录

饿汉式单例

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

饿汉式单例,在类第一次加载的时候,单例就完成了初始化,是线程安全的。

懒汉式单例

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

懒汉式单例,运用了延迟加载,在需要的时候进行初始化。

但多线程下有两个问题:

  1. 可能会得到不同的实例,违背了单例的初衷。
  2. 可能得到一个尚未初始化完全的对象。

怎样修改懒汉式单例才能保证线程安全性呢?

DCL+ volatile

DCL 即双重检查锁定机制

// 尝试一:锁可以保证线程安全性,但并发的情况下阻塞会导致效率低
public class Singleton {
    private static Singleton instance = null;
    synchronized public static Singleton getInstance(){
        if(instance == null){
            instance = new Singleton();
        }
        return instance;
    }
}

// 尝试二:缩小同步块的范围,有助于提高效率,但效果微乎其微
public class Singleton {
    private static Singleton instance = null;
    public static Singleton getInstance() {
        synchronized (Singleton.class) {
            if (instance == null) {
                instance = new Singleton();
            }
        }
        return instance;
    }
}

// 尝试三:继续缩小同步块的范围,效率明显提升,但得到的可能不是单例
public class Singleton {
    private static Singleton instance = null;
    public static Singleton getInstance() {
        if (instance == null) {
            synchronized (Singleton.class) {
                instance = new Singleton();
            }
        }
        return instance;
    }
}

// 尝试四:DCL,第一次空值检测对提升性能起到了很大的作用,但可能得到一个尚未初始化完全的对象
public class Singleton {
    private static Singleton instance = null;
    public static Singleton getInstance() {
        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

// 尝试五:在 DCL 基础上,为变量 instance 加上 voltile 关键字
public class Singleton {
    private volatile static Singleton instance = null;
    public static Singleton getInstance() {
        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

voltile 禁止了指令级并行的《重排序》,保证了初始化安全性。

懒汉式单例,使用 DCL + volatile,才具有线程安全性。

静态内部类实现单例模式

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

调用 getInstance 方法导致 Holder 类被加载,加载过程中初始化了单例。

而类的加载是加锁的,加载完成后才能加载另一个类,因此能够保证单例模式的安全性。

同时具有延时加载的特性。

单例模式

标签:机制   on()   zed   延迟加载   基础   初始   多线程   volatil   检测   

原文地址:https://www.cnblogs.com/xmsx/p/9752595.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!