• 并发编程(七)CAS原理解析


    一、引言

      前面的并发编程学习多次提到的CAS这个原理,也参考了不少CAS的文章,想想还是自己写一篇总结好好理解一下CAS原理吧,作为并发包的基石,CAS原理在提升性能方面是有很大的用处的,很有必要去专门下功夫了解一下。

    二、CAS的相关概念

    基础概念

      CAS:Compare and Swap,即比较再交换。

      主要步骤:冲突检测数据更新

      用处:可以实现乐观锁

    使用CAS之前存在的问题

      java在1.5之前都是靠synchronized关键字保证同步,synchronized是悲观锁,保证了无论哪个线程持有共享变量的锁,都会采用独占的方式来访问这些变量。这种情况下:

    • 1、在多线程竞争下,加锁、释放锁会导致较多的上下文切换和调度延时,引起性能问题
    • 2、如果一个线程持有锁,其他的线程就都会挂起,等待持有锁的线程释放锁。
    • 3、如果一个优先级高的线程等待一个优先级低的线程释放锁,会导致优先级倒置,引起性能风险。

      简单的来说就是会存在很多性能问题

    CAS原理分析

      核心操作:冲突检测数据更新

      特点:当多个线程尝试使用CAS同时更新同一个变量时,只有一个线程可以更新变量的值,其他的线程都会失败,失败的线程并不会挂起,而是告知这次竞争中失败了,并可以再次尝试

      三个操作数:

    • 需要读写的内存位置(V)
    • 预期原值(A)
    • 新值(B)

      一句话理解:我认为位置 V 应该包含值 A;如果包含该值,则将 B 放到这个位置;否则,不要更改该位置,只告诉我这个位置现在的值即可。

      PS:乐观锁是一种思想CAS只是这种思想的一种实现方式。、

      伪代码:

    //伪代码,解析CAS过程
    do{
        //1、备份旧数据(V)
        //2、把旧值设置为新值(B)
        //3、返回结果【成功返回新值(B),失败则返回旧的值(V)】
    }while(/*比较旧值(V)和预期值(A)是否相等*/);

      图解:

      场景:t1,t2线程同时更新同一变量100的值

      解析:

    • 1、因为t1和t2线程都同时去访问同一变量100,所以他们会把主内存的值完全拷贝一份到自己的工作内存空间,所以t1和t2线程的预期值都为100。
    • 2、假设t1在与t2线程竞争中线程t1能去更新变量的值,而其他线程都失败。PS:失败的线程并不会被挂起,而是被告知这次竞争中失败,并可以再次发起尝试
    • 3、t1线程去更新变量值改为101,然后写到内存中。此时对于t2来说,内存值变为了101,与预期值100不一致,就操作失败了【想改的值不再是原来的值】
    • 4、CAS 操作是基于共享数据不会被修改的假设,采用了类似于数据库的 commit-retry 的模式,当同步冲突出现的机会很少时,这种假设能带来较大的性能提升。

    三、CAS的应用

    PS:Unsafe为我们提供了硬件级别的原子操作

    四、ABA问题

    问题的产生

      首先我们看一下ABA问题是怎么产生的,网上有一个很好的例子,这里用来借鉴一下,感兴趣的同学可以点击参考文章中的【漫画:什么是CAS机制】来详细了解,作者讲解得非常好,强烈推荐关注下原文作者“程序员小灰”:

     

     

     

     

    解决方法

      解决方法:借助AtomicStampedReference类,加入版本号进行比较。

      原理:

    • 需要读写的内存位置(V)
    • 预期原值(A)
    • 新值(B)
    • 版本号(version)

      在原来的基础上加入版本号,读取公共变量的时候把当前版本号读取出来,比较的时候不仅比较内存位置值和预期原值,还要比较版本号,三者都相同时才进行替换。

      PS:详解AtomicStampedReference戳这里~

    参考文章:

  • 相关阅读:
    MySQL中的InnoDB中产生的死锁深究
    MySQL中的触发器应用
    你除了在客户端上会使用Cookie,还能使用哪些可以作为数据缓存呢?
    js中实现输入框类似百度搜索的智能提示效果
    linux系统中启动mysql方式已经客户端如和连接mysql服务器
    linux系统安装mysql数据库
    Linux中实用的命令
    Linux下安装jdk中遇到的坑
    Git初始化配置以及配置github
    springboot中配置文件使用2
  • 原文地址:https://www.cnblogs.com/riches/p/13859473.html
Copyright © 2020-2023  润新知