有关DCL、volatile之间的问题

4 篇文章 0 订阅

文章目录

名词介绍

  • DCL: Double check lock
  • 指令重排: java文件经过编译转化为字节码文件的时候,代码编译为一条条指令,一般来说是按照顺序执行的,但是比如说某条指令要从内存中拿数据,内存的速度要比cpu慢近乎百倍,这样cpu不可能等着该指令从内存中取到数据,所以就执行了后面的指令,这就是指令重排。
    无论是否指令重排,都保证了最终一致性
  • volatile: 多线程可见性、禁止指令重排(方式:指令屏障)

代码

@Data
public class Singleton {

    private String s;
    //这里为什么要用volatile:假如不使用volatile,可能导致指令重排,
    //例如在setS的之前,定义s1,s1完成了半初始化(也就是给s1分配完内存空间,完成了初始化,此时s1 = null,还没来得及完成将“指令重排”赋值于s1)的时候发生指令重排
    //接着执行,对INSTANCE完成了set值,此时有用到了INSTANCE的s发现s == null。错误
    //虽然以上说法有很大偶然性,但是多线程千奇百怪,哈哈哈
    private static volatile Singleton INSTANCE;
    private Singleton() {}
    private static Singleton getInstance() {
        //DCL 双检查单例。在多线程的情况下
        //如果不加锁,多个线程同时进入,判断INSTANCE为空后,获取多个实例,单例 的意义失效
        //加锁后要注意加锁粒度,尽量减小加锁的粒度,因为会影响执行效率;
        if (null == INSTANCE) {
            synchronized (Singleton.class) {
                //为什么要双检查:如果全部进入第一个null判断后,都在等待锁,如果不进行null判断,全部创建实例,单例失去意义
                if (null == INSTANCE) {
                    INSTANCE = new Singleton();
                    //业务代码
                    String s1 = "指令重排";
                    INSTANCE.setS(s1);
                }
            }
        }
        return INSTANCE;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值