文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

【JAVA】CAS总结

2023-09-24 12:55

关注

什么是CAS

CAS的全称为Compare-And-Swap,直译就是对比交换。是一条CPU的原子指令,其作用是让CPU先进行比较两个值是否相等,然后原子地更新某个位置的值,其实现方式是基于硬件平台的汇编指令,就是说CAS是靠硬件实现的,JVM只是封装了汇编调用。

简单解释:CAS操作需要输入两个数值,一个旧值(期望操作前的值)和一个新值,在操作期间先比较下在旧值有没有发生变化,如果没有发生变化,才交换成新值,发生了变化则不交换。

CAS操作是原子性的,所以多线程并发使用CAS更新数据时,可以不使用锁。

CAS的优缺点

优点:

  1. 由于CAS是非阻塞的,可避免死锁,线程间的互相影响非常小。
  2. 没有锁竞争带来的系统开销,也没有线程间频繁调度的开销。

缺点:

  1. 可能自旋循环时间过长。如果某个线程通过CAS方式操作某个变量不成功,长时间自旋,则会对CPU带来较大开销。怎么解决:限制自旋次数。
  2. 只是一个变量的原子性操作,不能保证代码块的原子性。
  3. ABA问题。

CAS底层原理

  1. java 的 cas 利用的的是 unsafe 这个类提供的 cas 操作。
  2. unsafe 的cas 依赖了的是 jvm 针对不同的操作系统实现的 Atomic::cmpxchg
  3. Atomic::cmpxchg 的实现使用了汇编的 cas 操作,并使用 cpu 硬件提供的 lock信号保证其原子性

CAS 可能会导致什么问题?

CAS存在ABA问题:

CAS 机制可以高效地实现原子操作,但仍不完美:

  1. 循环时间长开销大:CAS 大量失败后长时间占用 CPU 资源,加大了系统性能开销
  2. 只能保证一个共享变量的原子操作:当对一个共享变量执行操作时,我们可以使用循环 CAS 的方式来保证原子操作,但是对多个共享变量操作时,循环 CAS 就无法保证操作的原子性
  3. ABA 问题:CAS 机制本质上依赖值有没有发生变化的操作条件。但是如果值原来是 A、被改成变成了 B、最后又变回了 A,那么使用 CAS 进行检查时会发现它的值没有发生变化进行了操作,但是实际上却变化了,这其实违背了约定的条件。

Java的JUC包里有没有现成的类可以解决CAS的ABA问题?

public class ABADemo2 {//6为传入的值,1为版本号    static AtomicStampedReference<Integer> atomic = new AtomicStampedReference<>(6, 1);    public static void main(String[] args) {        //使用版本号机制来验证ABA问题        new Thread(() -> {            //获取当前版本号            int stamp = atomic.getStamp();            System.out.println("线程A1的版本号为:" + stamp);            try {                TimeUnit.SECONDS.sleep(1);            } catch (InterruptedException e) {                e.printStackTrace();            }//如果当前引用 等于 预期值并且 当前版本戳等于预期版本戳, 将更新新的引用和新的版本戳到内存//compareAndSet(V expectedReference,V newReference,int expectedStamp,int newStamp);            atomic.compareAndSet(6, 10, atomic.getStamp(), atomic.getStamp() + 1);            System.out.println("线程A2的版本号为:" + atomic.getStamp());            System.out.println(atomic.compareAndSet(10, 6, atomic.getStamp(), atomic.getStamp() + 1));            System.out.println("线程A3的版本号为:" + atomic.getStamp());        }, "线程A:").start();        //使用【乐观锁】思想解决ABA问题        new Thread(() -> {            int stamp = atomic.getStamp();            System.out.println("线程B1的版本号为:" + stamp);            try {                TimeUnit.SECONDS.sleep(1);            } catch (InterruptedException e) {                e.printStackTrace();            }            System.out.println(atomic.compareAndSet(6, 2, stamp, stamp + 1));            System.out.println("线程B2的版本号为:" + atomic.getStamp());        }, "线程B:").start();    }}

为什么会导致ABA问题?

这是因为 CAS 算法是在某一时刻取出内存值然后在当前的时刻进行比较,中间存在一个时间差,在这个时间差里就可能会产生 ABA 问题。

Java哪些地方使用了CAS?

Java提供的API中使用CAS的地方有很多,比较典型的使用场景有原子类、AQS、并发容器

CAS的实现离不开操作系统原子指令的支持,Java中对原子指令封装的方法集中在Unsafe类中,包括:原子替换引用类型、原子替换int型整数、原子替换long型整数。这些方法都有四个参数:var1、var2、var4、var5,其中var1代表要操作的对象,var2代表要替换的成员变量,var4代表期望的值,var5代表更新的值。

来源地址:https://blog.csdn.net/qq_41403267/article/details/131177920

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯