设计模式之单例模式

单例模式中使用volatile的目的:禁止指令重排序

DCL(Double Check Lock)双端检锁机制不一定线程安全,因为:在某个线程执行到第一次检测时,读取到的instance不为null时,instance对象可能没有完成初始化。
解释:
instance = new SingletonPattern();可以分为以下3步完成(伪代码)

1.分配内存对象空间:memory = allocate();
2.初始化对象:instance = (memory);
3.设置instance指向刚分配的内存地址,此时instance != null :instance = memory;

由于步骤2和步骤3不存在数据依赖关系,而且无论重排前还是重排后程序的执行结果在单线程中并没有改变,因此这种重排优化是允许的。

发生指令重排的情况:

1.分配内存对象空间:memory = allocate();
3.设置instance指向刚分配的内存地址,此时instance != null,但是对象初始化没有完成,就相当于这个地址空间内没有实际的值:instance = memory;
2.初始化对象:instance = (memory);

/**
 * 单例模式
 */
public class SingletonPattern {

    /**
     * 定义一个私有的静态singleton变量
     * volatile: 防止指令重排序
     */
    private static volatile SingletonPattern singleton = null;

    //私有的构造方法,限制其它类直接new一个实例对象,要获取对象,必须使用下面的getInstance()方法
    private SingletonPattern() {
        System.out.println("我是无参数的构造方法!!!");
    }

    /**
     * 静态的方法,可以使用类名调用,同时也可以直接使用静态变量singleton
     * 必须使用双重锁:当a,b两个线程都执行到同步代码块这里时,a线程进入同步代码块,实例化一个Singleton(),结束代码块的执行;
     * 这时b线程进来,如果不进行判断,又实例化一个Singleton(),singleton引用指向它; 之前的对象变为垃圾,待回收,没必要
     * @return
     */
    public static SingletonPattern getInstance() {
        //第一个if是避免同步阻塞等待
        if (singleton == null) {
            synchronized (SingletonPattern.class) {
                //第二个if是为了避免产生多个对象
                if (singleton == null) {
                    singleton = new SingletonPattern();
                }
            }
        }
        return singleton;
    }

参考链接:单例模式volatile分析

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值