6.互联网大厂高频面试题-cas

CAS是什么

cas:比较并交换(compareAndSet)
在这里插入图片描述
想突破一万五,必须要说得出底层!互联网公司不是不招,而是招高手。
在这里插入图片描述
多线程,发生的原子性问题,是因为执行太快发生了覆盖,值丢失了。
看方法的源码:
在这里插入图片描述
两个参数,一个是期望值,一个是更新值,主内存空间中有个变量a,3个线程把a复制到了工作内存中,然后想要修改主内存中的a,肯定希望此时主内存中还是自己复制过来的a,这就是第一个参数,期望值,如果不是a了,就返回false(整个流程就得重新取得主内存中的a的值,然后重复这个操作,直到期望值跟主内存中的值匹配起来。),如果是a,就返回true,并设置值。

测试代码:
在这里插入图片描述
在这里插入图片描述
这就说明,只有期望值和实际值一样,才会执行赋值操作,返回true,如果实际值不满足期望值,就会返回false,不会赋值。这就是最明显的比较并交换
总结:如果线程的期望值,跟物理内存的真实值一样,就修改为更新的值,本次操作为true,反之,为false。

CAS底层原理-上

底层原理,两个关键字:自旋锁、unsafe类。

atomicInteger.getAndIncrement()为啥可以保证原子性

getAndIncrement()用一个方法解决了i++在多线程环境下的线程安全的问题。
底层代码实现:调用的是unsafe类。
在这里插入图片描述
this:当前对象,valueoffset:内存偏移量,说白了就是内存地址。1是固定的。
这个方法的意思是:当前对象的内存地址值是多少?
在这里插入图片描述
这个类是运行时环境rt.jar提供支持的。
在这里插入图片描述
具体的位置在:
在这里插入图片描述
在这里插入图片描述
这个类大部分都是native级别的方法。
在这里插入图片描述
源码级别解读:unsafe类
在这里插入图片描述
value被volatile修饰,只要一变化,其他线程都可见。
静态代码块给调用unsafe类给内存偏移量赋值。
在这里插入图片描述
原子类之所以在多线程环境下不用加sync也能保证线程安全,是因为它用的是unsafe类。
在这里插入图片描述
可以用类似指针的方式,获取数据。获取的手段极度精确,如几排几列这种叫法。获取之后,执行加一的操作。
在这里插入图片描述
这个变量就是具体的值了。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
cas是cpu的原子指令,不会造成数据的不一致问题。也就是线程安全的。
在这里插入图片描述
在这里插入图片描述
var5是获得var1(传入的this,也就是当前对象)的var2(内存的偏移地址),可有理解为指针var5指向this的内存地址。
这个操作结束之后,进行while判断,var1的var2位置==var5的值是不是一致,如果是期望的值,那么就改为var5+var4,实现了加一。返回true,然后被取反就跳出了循环。如果不一致,则说明被人改过了,则返回false,取反为true,就继续循环,再去主内存拿一次值,直到比较成功。

cas底层原理-下

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
sync加锁同一时间段只允许有一个线程来访问,一致性得到了保障,但是大大降低了效率,并发性下降。使用cas没有加锁,匹配不上会循环比较,直到比较成功,大大提高了性能。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
总结:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

cas缺点

cas不加锁,保证了一致性,但是它有3个问题。
在这里插入图片描述

  • 循环时间长
    在这里插入图片描述
  • 只能保证一个共享变量的原子操作
    在这里插入图片描述
    多个变量只能加锁了。
  • 他会引出来ABA问题
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值