CAS Compare and Swap 比较后交换

CAS Compare and Swap 比较后交换

since: 2019年8月25日 22:44
auth: Hadi
update:2021年5月16日 22:55

CAS :Compare and Swap

字面意思就是比较后进行交换。在多线程中,经常有多个线程对一个公用变量进行值的更改和比较。那么在进行变量更改的时候,就必须考虑一致性的问题。

产生原因

当T1线程与T2线程在同时进行更改一个数据时,就会产生竞争的现象。如下图:
在这里插入图片描述

两个线程同时对一个变量进行++的操作,那么可能会导致取数时为1,进行各自local Memory的计算后写回主内存的时候都写为2。
那么最终得到的结果就为2,但真正的结果应该为3.

解决办法

当T1写入Main Memory的时候,进行预先判断,判断写入之前的值是否是我操作之前的值,如果是那么就进行写入。当T2进行写入的时候,采用同样的操作,却发现并不是我之前操作的值,那么就会重新read MainMemory中的这个值,并重新进行整个流程。

使用场景

  • 自旋锁
  • Unsafe类

在atomic类中,比如 atomicInteger.getAndIncrement(); 自增,没有加syn也没有出错
在这里插入图片描述
其直接调用了unsafe类的getAndAddInt方法(这个类, 内存地址, 自增值),在atomic类中这样构造:
在这里插入图片描述

注意 unsafe使用Unsafe.getUnsafe()获得
valueOffset 是内存地址(偏移量)
而unsafe是 sun.misc 下的。
是CAS的核心类,由于Java方法无法直接访问底层系统,需要通过本地native 方法来访问,Unsafe相当于一个后门,基于该类可以直接操作特定的内存数据。

unsafe的内部方法可以向C的指针一样直接操作内存。
Native 修饰的方法,直接调用操作系统底层资源执行相应任务 某个.dll

那如果比较后,其他线程进行了更改怎么办?还是会导致写覆盖

CAS的全称为 CompareAndSwap 是一CPU并发原语
他的功能是判断内存某个位置的值,是否为预期值,如果是则更改为新的值,这个过程是原子的。

体现在JAVA语言中就是sun.misc.Unsafe类中的各个方法。调用Unsafe类中的CAS方法,JVM会帮我们实现出CAS汇编指令。这是一种完全依赖于硬件的功能,通过它实现了原子操作。再次强调,CAS是一种系统原语,是由若干条指令组成的,用于完成某个功能的一个过程。
并且原语的执行必须是连续的,在执行过程中不允许被中断,也就是CAS是一条CPU原子指令,不会造成所谓的数据不一致问题。

  • AtomicInteger.getAndIncrement();
    在这里插入图片描述

  • unSafe
    在这里插入图片描述

  • compateAndSwap 其实应该是 对象,地址, 以前的值, 想要更改的值
    在这里插入图片描述

为什么用CAS 不用syn

syn同一时间只允许一个线程访问。但CAS其实是多个线程允许一起访问的,且不会阻塞。

CAS的缺点

循环之间长,开销很大。
只能保证一个共享变量的原子操作。
引出来ABA问题。

ABA问题

可能当我比较的时候确实是原来的值,但其实在中途已经被更改过多次了,并不是原来的版本;在某些场景下必须进行版本的控制,则可以在此之上进行版本相关的控制。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值