并发编程-CAS

目录

原理

具体解释

CAS伪代码实现

[CAS 的应用场景](#CAS 的应用场景)

[CAS 的优劣点](#CAS 的优劣点)

ABA问题

解决ABA问题的方式


原理

Compare And Swap(比较再交换):在更新前检查数据是否被修改,若未被修改,则更新,否则自旋重试

具体解释

主存中有一个共享变量,当线程想要去修改这个变量的值的时候,需要先把这个变量的值拷贝到线程的工作内存中,然后进行计算操作,得到一个新的值。然后线程带着旧值和新值再次找到主存中的共享变量。

先比较旧值和现在主存中的共享变量是否相同。

  • 若相同,说明在这期间没有其他线程修改过主存中的共享变量,是线程安全的。因此把新值写入主存的共享变量中。

  • 若不同,说明在这期间有其他线程修改过主存中的共享变量,不是线程安全的。因此此时需要自旋重试

    • 自旋:再次取得主存中共享变量的值。回到线程的工作内存进行计算操作得到新值。再次比较旧值和主存中的共享变量的值是否相同。又回到刚刚的逻辑。直至自旋成功。

CAS 伪代码实现

java 复制代码
class AtomicInteger {  //返回自增前的值
    private int value; // 共享变量,在主存中

    public int getAndIncrement() {
        int oldValue = value; // 第一次读取主存中的值到线程工作内存,相当于这就就是"旧值"
        while (CAS(value, oldValue, oldValue + 1) != true) { 
        // 线程带着"旧值":oldvalue和"新值"oldValue+1,用"旧值"和主存中的共享变量作比较
            oldValue = value; // 如果失败,说明值被其他线程改了,重新读取最新值
        }
        return oldValue; // 返回的是更新前的旧值
    }
}

CAS 的应用场景

  • AQS中大量使用到CAS来实现基本操作。

  • JUC包下的原子类中(例如AtomicInteger) 大量使用到CAS + volatile来保证线程安全。

CAS 的优劣点

优点:CAS是一种乐观锁,不加锁,无锁并发保存线程安全。

缺点:

  • 自旋占用CPU

  • 可能会导致ABA问题

ABA问题

在做CAS操作时

  • 线程1获取值为A

  • 线程2修改值为B

  • 线程3修改值为A

  • 线程2获取值还是为A,以为该值从未被修改过,这就是ABA问题

解决ABA问题的方式

思路:使用带有版本号的CAS(比如使用AtomicStampedReference类)

  • 该类的原理是引入一个版本号,每次操作,都会给版本号一个新值。进行CAS操作时,不仅要求数值要和之前一样,版本号也要一样。

  • 当数值一样,但是版本号不同时,说明发生了ABA问题,此时值不会被修改

相关推荐
Maỿbe6 个月前
java中的CAS机制
java·线程·进程·cas
mikey棒棒棒10 个月前
Redis——优惠券秒杀问题(分布式id、一人多单超卖、乐悲锁、CAS、分布式锁、Redisson)
数据库·redis·lua·redisson·watchdog·cas·并发锁
xweiran1 年前
CAS操作的底层原理(总线锁定机制和缓存锁定机制 )
java·cas·处理器·总线锁定·缓存锁定
跳跳的向阳花1 年前
04、JUC并发编程之:简单概述(四)
java·开发语言·cas·juc·volatile·原子引用·原子整数
问道飞鱼1 年前
【Springboot知识】Springboot进阶-实现CAS完整流程
java·spring boot·后端·cas
阿维的博客日记1 年前
jvm学习笔记-轻量级锁内存模型
jvm·cas·轻量级锁
Hello-Brand1 年前
架构与思维:漫谈高并发业务的CAS及ABA
高并发·cas·aba
GGBondlctrl1 年前
【JavaEE初阶】深入理解不同锁的意义,synchronized的加锁过程理解以及CAS的原子性实现(面试经典题);
java·开发语言·面试·cas·synchronized加锁·锁的策略
一只BI鱼1 年前
CAS简单解析
java·cas·乐观锁