Concurrent -- 02 -- CAS源码解析

原文链接:Concurrent – 02 – CAS源码解析


相关文章:


CAS (Compare And Swap),即比较并交换,是一种高效实现线程安全的方法,其需要三个操作数,分别是内存地址 (在 Java 中可以简单地理解为变量的内存地址,用 V 表示)、旧的预期值 (用 A 表示) 和准备设置的新值 (用 B 表示)

  • 属于乐观锁机制

  • 支持原子性更新操作,适用于计数器、序列发生器等场景

  • CAS 操作失败时,由我们自行决定是否继续尝试,还是执行别的操作

当执行 CAS 指令时,当且仅当 V 符合 A 时,处理器才会用 B 去更新 V 的值,否则它就不执行更新,但不管是否更新了 V 的值,最终都会返回 V 的旧值,上述处理过程为原子操作,执行期间不会被其他线程中断


一、CAS 实现

  • JUC 的 atomic 包中提供了常用的原子性数据类型以及引用、数组等相关原子类型和更新操作工具,是很多线程安全程序的首选

  • Unsafe 类虽然提供 CAS 服务,但其能够操纵任意内存地址的读写而存在隐患

  • 从 Java 9 开始,可以使用 Variable Handle API 来替代 Unsafe

  • 代码示例

    public class CASTest {
    
        private static AtomicInteger count = new AtomicInteger(0);
    
        public static void increase() {
            count.getAndIncrement();
        }
    }
    
    • 如上所示,由于调用了 count 的原子自增方法,increase() 方法在多线程调用的情况下,不会出现线程安全问题

二、CAS 存在的问题

  • 若循环时间过长,则开销会很大

  • 只能保证一个共享变量的原子操作

  • 存在 ABA 的问题 (可以使用 AtomicStampedReference 来解决 ABA 的问题)

    • 代码示例

      public class ASRTest {
      
          public static void main(String[] args) {
              String V = "aaa";
              String A = "aaa";
              String B = "bbb";
              // 将版本号设置为1
              AtomicStampedReference<String> asr = new AtomicStampedReference<>(V, 1);
              // 进行CAS操作(A -> B)
              asr.compareAndSet(A, B, asr.getStamp(), asr.getStamp() + 1);
              // 进行CAS操作(B -> A)
              asr.compareAndSet(B, A, asr.getStamp(), asr.getStamp() + 1);
              // 此时期望的版本号为 1,而实际上版本号为 3,两者不相同,故CAS操作失败
              boolean isOk = asr.compareAndSet(A, B, 1, asr.getStamp() + 1);
              System.out.println(isOk); // false
              System.out.println(asr.getStamp()); // 3
          }
      }
      
      • 如上所示,我们定义了一个 AtomicStampedReference 类型的变量 asr,其版本号为 1,然后模拟 ABA 操作 (即进行了两次 CAS 操作),最后想将 A 的值设置为 B,期望的版本号为 1,而实际上版本号为 3,两者不相同,故 CAS 操作失败

三、归纳总结

  • 悲观锁

    • 总是假设最坏的情况,每次取数据都认为会被其他线程修改,所以每次在取数据的时候都会加上锁
  • 乐观锁

    • 总是假设最好的情况,每次取数据都认为不会被其他线程修改,所以不会上锁

    • 可以通过版本号机制或 CAS 算法来实现

  • CAS 存在的问题

    • 若循环时间过长,则开销会很大

    • 只能保证一个共享变量的原子操作

    • 存在 ABA 问题

  • 如何解决 CAS 中的 ABA 问题

    • 使用版本号机制来解决

四、参考资料

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值