CAS Compare and Swap 比较后交换

Posted 青冬

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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问题

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

以上是关于CAS Compare and Swap 比较后交换的主要内容,如果未能解决你的问题,请参考以下文章

CAS(Compare and swap)比较并交换算法解析

CAS Compare and Swap 比较后交换

CAS(Compare and Swap)理解

每日一博 - CAS(Compare-And-Swap)原理剖析

非阻塞同步算法与CAS(Compare and Swap)无锁算法

JUCCAS(Compare And Swap)及其ABA问题