java中的双重检查锁,为什么会用到volatile关键字?

双重检查锁(Double-Checked Locking)是一种常见的用于实现线程安全单例模式的技术,它的目标是在保证线程安全的前提下,尽可能地减少锁的使用,从而提高程序的性能。

使用双重检查锁实现单例模式:

public class Singleton {
    // 声明一个volatile类型的静态变量,保证多线程环境下对其可见性
    private static volatile Singleton instance;

    // 私有化构造方法,保证外部不能通过构造方法创建实例对象
    private Singleton() {}

    // 静态方法获取单例实例
    public static Singleton getInstance() {
        // 判断实例是否为null,如果为null则进入同步代码块(第一次检查)
        if (instance == null) {
            // 使用类级别的锁,保证同一时间只有一个线程进入同步代码块
            synchronized (Singleton.class) {
                // 第二次检查实例是否为null,因为可能有多个线程同时进入上一个if语句块
                if (instance == null) {
                    // 创建实例对象并赋值给instance变量
                    instance = new Singleton();
                }
            }
        }
        // 返回单例实例
        return instance;
    }
}

为什么instance要声明为volatile类型?

事实上,对于示例中17行的代码 instance=new Singleton(); 创建了一个象。一 行代码可以分解如下的3

memory = allocate(); // 1:分配对象的内存空间
ctorInstance(memory); // 2:初始化对象
instance = memory; // 3:设置instance指向刚分配的内存地址
上面3行伪代码中的2和3之间,可能会被重排序。2和3之间重排序之后的执行时序如下。
memory = allocate(); // 1:分配对象的内存空间
instance = memory; // 3:设置instance指向刚分配的内存地址。注意,此时对象还没有被初始化!
ctorInstance(memory); // 2:初始化对象

如果发生重排序,另一个并发执行的线程B就有可能在第4行判断instance不为null。线程B接下来将访问instance所引用的对象,但此时这个对象可能还没有被A线程初始化。

instance要声明为volatile本质上是通禁止23的重排序,来保证线程安全的延初始化。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值