Android的单例模式

1.直接实例化对象并返回

public class Single {
//直接生成
	private static final Single instance1 = new Single();
	public static Single getInstance1() {
	    return instance1;
	}
}

2.静态内部类

 public class Single {
    //静态内部类
    public static final class Holder {
        private static final Single instance2 = new Single();
    }

    public static Single getInstance2() {
        return Holder.instance2;
    }
 }

3.双重检查锁

public class Single {
	private static volatile Single instance3 = null;
    public static Single getInstance3() {
        if (instance3 == null) {
            synchronized (Single.class) {
                if (instance3 == null) {
                    instance3 = new Single();
                }
            }
        }
        return instance3;
    }
}

问题1.为什么使用volatile关键字

线程的三要素:原子性,可见性,有序性
volatile的实现原理:内存屏障

当CPU写数据时,如果发现一个变量在其他CPU中存有副本,那么会发出信号量通知其他CPU将副本对应的缓存行置为无效状态,当其他CPU读取到变量副本的时候,会发现该缓存行是无效的,会从主存中重新读取变量

volatile的三个作用(保证可见性+有序性)
1.解决多核CPU高速缓存导致的变量不同步,保证线程的可见性

CPU的高速缓存速度远远快于主存(物理内存)

CPU在读取一个变量时,会把数据先读到缓存,这样下次再访问同一个数据时直接从缓存读取,提高了读取性能,多核CPU则有多个这样的缓存。

这样引发的问题:当CPU1修改了这个变量(比如把a的值从1修改为2),但是其他CPU(比如CPU2)在修改之前就已经将a=1读取到自己的缓存了,当CPU2再次读取自己的数据的时候,会优先从自己的缓存区读取,此时读到的还是1,实际上a=2了

因此volatile可以保证线程的可见性。

线程可见性:多个线程在访问同一个变量时,如果其中一个线程修改了变量的值,那么其他线程应能立即看到修改的后的值

2.解决指令重排序的问题

单线程执行下:CPU保证了指令顺序不一定一致,但结果一定一致

多线程会引发出错,比如:

New 一个对象有三个步骤

1 开辟内存
2 对象赋值地址
3 初始化

如果发生指令重排,步骤为1,3,2,当进行到1,3的时候发生异常,此时的对象并不是一个完整的对象,但是此对象不为null。
因此,需要禁止指令重排。

3.不保证原子性

原子性:一个或多个操作,要么全部连续执行且不被任何元素中断,要么都不执行

问题2.为什么使用两重检查(if (instance3 == null) )

一重判断:如果不为空,直接返回 不用进锁,节约时间

二重:还需要判断 instance 是否为空,是为了防止在多线程并发的情况下,会实例化多个对象

例如:线程 a 和线程 b 同时调用 getInstance 方法,假如同时判断 instance 都为空,这时会同时进行抢锁。
假如线程 a 先抢到锁,开始执行 synchronized 关键字包含的代码,此时线程 b 处于等待状态。
线程 a 创建完新实例了,释放锁了,此时线程 b 拿到锁,进入 synchronized 关键字包含的代码,
如果没有再判断一次 instance 是否为空,则可能会重复创建实例。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值