Java CAS概述

CAS是什么?

CAS表示比较并交换,它是一条cpu并发原语指令。
我们在多线程开发环境当中不免会使用到AtomicInteger类来保证多线程安全性
例如:

  AtomicInteger atomicInteger = new AtomicInteger(3);
  atomicInteger.getAndIncrement();

点进去getAndIncrement()方法里面会有

public final int getAndIncrement() {     //valueOffset是内存偏移量 内存地址
    return unsafe.getAndAddInt(this, valueOffset, 1);
}

调用CAS的unsafe类中的方法 JVM会实现汇编指令,这种指令是依赖于一种硬件的操作,通过它来实现原子操作
以unsafe.getAndAddInt(this, valueOffset, 1);为例

public final int getAndAddInt(Object var1, long var2, int var4) {
   int var5;
   do {//自旋
        var5 = this.getIntVolatile(var1, var2); //先从内存中拿当前对象的快照
   } while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));//比较并交换
   return var5;
 }

代码解释:
var1 AtomicInteger对象本身
var2 当前对象在内存里面的偏移量(引用地址)
var4 需要变动的量,此处为1
var5 是通过var1 var2在主内存里面的真实的值
先从内存中拿到快照(var5) , 比较并交换时:先查看var1对象通过var2地址在内存中的真实值 与期望值进行比较,如果期望值没有被修改则比较交换完成, 最终值为var5+var4

以代码为例子以更好的体会CAS

假设有两个线程A、B
1.AtomicInteger里面的value原始值为3,即主内存中AtomicInteger的value为3,根据JMM模型,线程A和线程B各自持有一份值为3的value的副本分别到各自的工作内存.

2.线程A通过getIntVolatile(var1,var2) 拿到value值3,这时线程A被挂起.

3.线程B也通过getIntVolatile(var1,var2) 拿到value值3,此时刚好线程B没有被挂起并执行compareAndSwapInt方法比较内存中的值也是3 成功修改内存的值为4 线程B打完收工 一切OK.

4.这时线程A恢复,执行compareAndSwapInt方法比较,发现自己手里的数值和内存中的数字4不一致,说明该值已经被其他线程抢先一步修改了,那A线程修改失败,只能重新来一遍了.

5.线程A重新获取value值,因为变量value是volatile修饰,所以其他线程对他的修改,线程A总是能够看到,线程A继续执行compareAndSwapInt方法进行比较替换,直到成功.

CAS的缺点

1.cas失败会一直在尝试,如果cas长时间不成功会给cpu带来很大的开销
2.只能保证一个共享变量的原子操作
3.这样可能会导致ABA问题

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值