CAS原理

CAS是什么:
CAS是CPU并发原语,由于CAS是系统原语,由若干条指令组成,而且原语在执行的过程中必须是一致的,所以CAS是线程安全的。CAS算法是一种无锁算法,但是CAS可以理解成不同于synchronouse的乐观锁。
CAS基本原理:
CAS有3个操作数,内存值V,旧的预期值A,要修改的新值B。当且仅当预期值A和内存值V相同时,将内存值V修改为B,否则什么都不做。

//代码模拟简易过程
AtomicInteger atomicInteger = new AtomicInteger(10);
// 10为期望值(A),1为新值(B)
// 将主内存的值修改为1 修改成功,主内存值为1(V)
atomicInteger.compareAndSet(10, 1)
// 主内存的值为1 ,但是当前期望值是10,那么V和A值不同,修改失败
atomicInteger.compareAndSet(10, 2)

在这里插入图片描述
CAS底层原理:
CAS会把当前工作内存中的值和主内存中的值相比较,如果相同则执行后续操作,否者继续自旋偏移取主内存的值比较,直到主内存和工作内存的值一致为止。
基于jdk1.8.0_20 部分源码

//Unsafe是CAS的核心类,Java无法操作底层系统,Unsafe就可以操作底层(Unsafe内部方法由native修饰)
//此方法块的意思就是获取value值在工作内存中的偏移量valueOffset 
private static final Unsafe unsafe = Unsafe.getUnsafe();
static {
	try {
//假如线程1和线程2都从主内存获取的变量值为10,先通过此方法获取10在工作内存的偏移量	
	valueOffset = unsafe.objectFieldOffset
			(AtomicInteger.class.getDeclaredField("value"));
	} catch (Exception ex) { throw new Error(ex); }
}

//通过valueOffset,直接通过内存地址,获取到值,然后把主内存值加20
public final int getAndIncrement() {
	return unsafe.getAndAddInt(this, valueOffset, 20);
}

//var1为this,AtomicInteger对象本身
//var2为valueOffset
//var4为要增加的值
public final int getAndAddInt(Object var1, long var2, int var4) {
	int var5;
	do {
		//通过对象和valueOffset拿到主内存中真实的值(var5)
		var5 = this.getIntVolatile(var1, var2);
		//执行compareAndSwapInt比较工作内存中的值和主内存的值是否相等
		//如果主内存中的值(var5)=工作内存的值value,则将值设为var5+var4,并返回true,否则返回false
		//假如线程1执行完毕了,返回了true,那么主内存的值就变成了30,那么线程2的工作内存的值还是10,而主内存是30,显然他们不相等,就返回false,执行执行do-while循环重新获取主内存的值
	} while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));
	return var5;
}

CAS缺点:
ABA问题(CAS每次更新主内存的值之前都会拿之前从主内存取的值A和现在从主内存取的值B相比较,如果一致就更新,不一致就不更新,可以通过增加版本号解决此问题)
循环时间长,开销大(它的自旋会导致开销大)
无法对多个共享变量保证原子性,只能对一个共享变量(对多个共享变量就要加锁了)

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值