懒汉模式和恶汉模式笔记-双重检查锁单例模式

 

懒汉模式=懒得生成实例,增加逻辑判断,线程不安全,适合使用频率低,有线程安全问题

饿汉模式=出生自带实例,因为static修饰的变量指向实例对象,牺牲空间,适合于使用频率高

 

懒汉模式:如果没有1,虽然将synchronized从0移到2缩小了粒度(不在方法上加锁),但是每次线程进来都会加锁进去判断,所以线程多的话会阻塞

于是加上1,去判断有没有必要去加锁,只要对象生成,之后的线程就没有阻塞问题,只有在第一个线程加锁到解锁进来的线程会阻塞

private static Singleton instance;public static Singleton getInstance()//0
{
  if (instance == null)//1
  {
    synchronized(Singleton.class) {  //2
      if (instance == null)          //3
        instance = new Singleton();  //4
    }
  }
  return instance;
}

但是instance = new Singleton()需要分为三步指令执行

4.1 分配对象内存

4.2初始化对象

4.3引用变量指向对象分配的内存

存在指令重排问题,可能会重排序成以下三步指令

4.1 分配对象内存

4.3引用变量指向对象分配的内存

4.2初始化对象

先执行4.3之后,引用非空(!=null)

在4.3到4.2之间,对象未初始化,其他线程(1这步判断的线程不会加锁,可以理解为另一个线程,与走锁的线程区分开来)进来,判断非空,使用时指向该对象的内存空间发现没有初始化,报错。

虽然加锁保证了抢锁的线程会等待上一个持有锁的线程执行完毕,然后抢到锁之后重新更新instance的值,达到原子性和可见性的目的,但是对于非抢锁线程,指令重排序会将instance的值提前暴露给这些线程

解决方法:使用volatile修饰instance 变量,防止指令重排序

private static volatile Singleton instance;

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值