zoukankan      html  css  js  c++  java
  • CAS及其ABA问题

          CAS、volatile是JUC包实现同步的基础。Synchronized下的偏向锁、轻量级锁的获取、释放,lock机制下锁的获取、释放,获取失败后线程的入队等操作都是CAS操作锁标志位、state、队列完成的。

    CAS过程

         CAS的全称是Compare And Swap 即比较交换 ,是系统原语,由一系列系统的指令组成,不可被分割,简单的说就是CAS操作时一个原子性的操作。在sun.misc.unsafe类中,所有方法都是native的,都直接调用操作系统底层资源执行相应任务,比如直接操作内存,Java中CAS操作的执行依赖于Unsafe类的方法。其算法核心思想如下

    其包含3个参数

    • V表示要更新的变量(即内存中的某变量的当前值)

    • E表示预期值

    • N表示新值

           CAS操作需要我们提供一个期望值E,当 E == V 时,说明还没线程修改该值,当前线程可以进行修改为N,但如果期望值与当前线程不符,则说明该值已被其他线程修改,此时不执行更新操作,但可以选择重新读取该变量再尝试再次修改该变量 (也叫自旋) ,也可以放弃操作。

    CAS的ABA问题

          虽然CAS可以用很小的开销完成某些需要同步的操作,但也存在一些问题,比如ABA问题,并发量大的情况下自旋消耗过大的问题。关于ABA问题,举例说明:

           我买东西付款100元后,由于一些原因,发起了两个付款线程 1、2。线程1 预期我的账户内存中的值为A元钱,要把它-100修改为B元。

           这时线程1阻塞了,线程2顺利执行把A改为B。(正常情况下,线程1应该是CAS失败的,因为内存值B以经不等于它的预期值A了)

           线程1还没来得及继续执行,你给我转账100元,并且这个转账 线程3 顺利执行完毕,我的账户+100,又变成A元。

           在转账线程3完成后,线程1终于又开始执行了,它发现内存值还是A,于是它会执行扣款操作。我平白无故损失100元。

    简单的说,ABA问题是: 两个进行同样操作的线程,本来是应该只能有一个操作成功,但是由与第三者介入二者之间修改数据,迷惑了二者中后执行的线程,使两个线程同样的操作都执行成功了。  比如扣了两次款!

          解决办法是给我的余额值加个版本号,经过一次修改就更新一次版本。对于有些情况, 预期中的值、版本号 == 内存中值、版本号, 即二者都想等,才执行更新操作。

           

            

  • 相关阅读:
    新一代MQ apache pulsar的架构与核心概念
    Flutter使用fluwx实现微信分享
    BZOJ3622 已经没有什么好害怕的了 动态规划 容斥原理 组合数学
    NOIP2016提高组Day1T2 天天爱跑步 树链剖分 LCA 倍增 差分
    Codeforces 555C Case of Chocolate 其他
    NOIP2017提高组Day2T3 列队 洛谷P3960 线段树
    NOIP2017提高组Day2T2 宝藏 洛谷P3959 状压dp
    NOIP2017提高组Day1T3 逛公园 洛谷P3953 Tarjan 强连通缩点 SPFA 动态规划 最短路 拓扑序
    Codeforces 873F Forbidden Indices 字符串 SAM/(SA+单调栈)
    Codeforces 873E Awards For Contestants ST表
  • 原文地址:https://www.cnblogs.com/shen-qian/p/11238999.html
Copyright © 2011-2022 走看看