为什么要双重检查锁 为什么要加volatile

1. 饿汉式
public class Singleton { 
  private static final Singleton instance = new Singleton();

  private Singleton() {}

  public static Singleton getInstance() {
    return instance;
  }
}

2. 懒汉式
public class Singleton {
    private static Singleton instance;

    private Singleton() {
    }

    public synchronized Singleton getInstance() {
        if (null == instance) {
            instance = new Singleton();
        }
        return instance;
    }
}


3. 双重检测
public class Singleton { 

  private static Singleton instance;

  private Singleton() {}

  public static Singleton getInstance() {
    if (instance == null) {
      synchronized(Singleton.class) { // 此处为类级别的锁
        if (instance == null) {
          instance = new Singleton();
        }
      }
    }
    return instance;
  }

}



双重检查锁疑问:  https://blog.csdn.net/xiakepan/article/details/52444565

问:我的疑问是有synchronize同步,就算java有指令重排序,也应该是线程1按132顺序全部执行完线程2才能拿到锁吧.

答: 现在关键点不是拿到锁的问题。而是在第一重非空判断。 如果指令重排,线程A先将没初始化完成的实例刷新回主存,那么线程B在第一重非空判断时候就直接返回了不完整对象,与锁没关系。

昨晚查了下,其实在释放锁时,只是保证必须要把变量写回主存,但不代表只有在释放锁时才会写,之前也可能会更新变量就写回主存,所以这里确实是必须要加volatile的,不然确实可能会拿到未促使化完成的对象,引发空指针异常

 

 

https://www.cnblogs.com/xz816111/p/8470048.html

 

 

 

 

为了解决上述问题,需要在uniqueSingleton前加入关键字volatile。使用了volatile关键字后,重排序被禁止,所有的写(write)操作都将发生在读(read)操作之前。

至此,双重检查锁就可以完美工作了。

https://segmentfault.com/q/1010000014296501

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值