美文网首页
JAVA-CAS基本原理

JAVA-CAS基本原理

作者: 超人TIGA | 来源:发表于2021-03-13 11:55 被阅读0次
什么是CAS?

compare and swap:比较和交换

那java什么地方需要这个呢?先介绍下几个概念性的东西

原子性是什么?
原子性就是最小单位,原子性操作就是最小的操作,无法再进一步分割,这操作的结果只有2种,完成或者未完成。
例如 int a = 1,这种就是原子性操作。
而a++,这个就不是原子性操作,因为a++,会拆解为3步,读取a的值,a增加1,再把a的值刷新。

还是那个例子,2个线程,同时对一个变量a进行递增,每次+1,递增100次。当2个线程都执行完毕,a的结果不会是200,会小于200。

为什么会这样?
其实这就是上面说的原子性问题,一开始a=0,线程A启动,执行a++,但是a++总共有3步,当线程A读取a的值(此时为0),然后递增1(a值为1),这是线程B启动,读取a值,由于线程A的a值尚未刷新回去,所以线程B获取到的值依然是0,而不是1,最终执行完毕的结果,就已经不是我们想要的结果了。

解决办法有哪些?
根据上面的例子,多线程处理资源嘛,肯定第一时间就会想到加个锁,因为锁能保证一段代码块执行完毕,从而保证原子性。
但是,如果要执行的代码足够简单的时候,例如上面的只有个a++,使用锁的话,会十分浪费,性能也不高,因为一个线程获得了锁,其他线程都无法进行了。
所以,就需要用到了CAS

image.png
CAS其实就是实现一种乐观的自旋锁,相较于synchronize的悲观锁,没有阻塞状态,自然也就没有上下文的切换了,而线程状态的切换,耗时比CAS的自旋比较操作耗时大得多。
CAS的缺点

①ABA问题
简单地描述,就是值被中途修改过的问题。
变量a=0
线程A:执行a++
线程B:执行a=10,然后再a=0
有一种情况,当线程A已经读取了a的值(0),然后线程B执行,a值先变为了10,后变回0,之后线程A再CAS,由于和预期一致,所以能赋值成功。
这种就是CAS的ABA问题,当然,如果我们不关心a值是否被改动过,只关心结果,那其实也无所谓。
解决方法就是加个版本戳。

②开销问题
成也自旋,败也自旋。当资源竞争足够大,成千上亿个线程去同时争一个资源,那其实大部分时候,大部分的线程都是在compare和重新获取的过程中,就会造成CPU的繁忙。

③只能保证一个共享变量的原子性
CAS的机制就是比较并且交换,只是针对一个资源。如果同时要保证多个资源的原子性,就不适合了,这时候就要用synchronize锁了。

那CAS用在什么地方?

其实JAVA的api包已经帮我们实现了很多了,我们只要拿来用就行,就是atomic的包,例如automicInteger。
调用过程

2101497-20200725163230608-1790748047.png
可以看到,最终就是调用compareAndSwapInt方法。它会用var1和var2先获取内存中AtomicInteger中的值,然后和传入的,之前获取的值var5做一下比较,也就是比较当前内存的值和预期的值是否一致,如果一致就修改为var5 + var4,否则就继续循环,再次获取AtomicInteger中的值,再进行比较并交换,直至成功交换为止。

我们假设两个线程交替运行的情况,看看它是怎样工作的:
初始AtomicInteger的值为0
线程A执行:var5 = this.getIntVolatile(var1,var2);获取的结果为:0
线程A被暂停
线程B执行:var5 = this.getIntVolatile(var1,var2);获取的结果为:0
线程B执行:this.compareAndSwapInt(var1,var2,var5,var5 + var4)
线程B成功将AtomicInteger中的值改为1
线程A恢复运行,执行:this.compareAndSwapInt(var1,var2,var5,var5 + var4),此时线程A使用var1和var2从AtomicInteger中获取的值为:1,而传入的var5为0,比较失败,返回false,继续循环。
线程A执行:var5 = this.getIntVolatile(var1,var2);获取的结果为:1
线程A执行:this.compareAndSwapInt(var1,var2,var5,var5 + var4),此时线程A使用var1和var2从AtomicInteger中获取的值为:1,而传入的var5为1,比较成功,将其修改为var5 + var4,也就是2,将AtomicInteger中的值改为2,结束。

相关文章

  • JAVA-CAS基本原理

    什么是CAS? compare and swap:比较和交换 那java什么地方需要这个呢?先介绍下几个概念性的东...

  • JAVA 中的 CAS

    原文地址:https://www.xilidou.com/2018/02/01/java-cas/ CAS 是现代...

  • Java-CAS

    原子性操作 原子即为不可再分的,原子操作即要么所有操作全部完成 要么全不完成。用synchronized包围的代码...

  • java-cas与锁比较

    一张图整体了解java concurrent包 CAS实现了区别于synchronouse同步锁的一种乐观锁。其与...

  • 逻辑学的基本原理

    01 基本原理 任何科学都是由包含基本原理的知识组成的。 任何科学的基本原理都是这门科学赖以...

  • 2018-08-26日更

    基本原理任何科学都是包含基本原理的知识组成的。逻辑学的基本原理和人类理性的基本原理是一致的。 同一律 表述:事物只...

  • 初识jQuery

    初识jQuery[jQuery基本原理](# jquery基本原理)[jQuery和JavaScript的区别](...

  • GAN

    基本原理 GAN(Generative Adversarial Networks) 的基本原理其实非常简单,这里以...

  • Android DLNA投屏-基于CyberGarage开发投屏

    在上一篇博客《Android DLNA投屏-基本原理》中,讲到了DLNA的一些基本原理。了解这些基本原理,对开发是...

  • Spring Security

    基本原理 Spring Security 基本原理(如下图): 认证模块(绿色): 账户密码 /login.htm...

网友评论

      本文标题:JAVA-CAS基本原理

      本文链接:https://www.haomeiwen.com/subject/ffmnqltx.html