CAS

CAS

为啥可以实现原子操作
使用硬件cpu指令来执行,
CAS_第1张图片
且硬件cpu 指令为 cmpxchg

那么compareAndSet是做什么的呢?

理解这个方法我们需要引入CAS操作AtomicInteger 中的CAS操作就是compareAndSet(),其作用是每次从内存中根据内存偏移量(valueOffset)取出数据,将取出的值跟expect 比较,如果数据一致就把内存中的值改为update。

一.概述

CAS全称CompareAndSet***,其下的实现都是通过sun包下Unsafe类实现的,而Unsafe类中的方法都是native修饰的(即由Jvm本地实现),提供了硬件级别的原子操作。
CAS(比较并交换)是CPU指令级的操作,只有一步原子操作,所以非常快。是一种乐观锁。

可以查看Unsafe类下的
public final native boolean compareAndSwapObject(Object var1, long var2, Object var4, Object var5);

public final native boolean compareAndSwapInt(Object var1, long var2, int var4, int var5);

public final native boolean compareAndSwapLong(Object var1, long var2, long var4, long var6);

CAS(Compare and Set 即比较并交换) ,设计并发算法时常用到的一种技
术, java.util.concurrent.atomic 包下的原子操作类都是基于 CAS 实现的。

CAS 有三个操作数:内存值 V、旧的预期值 A、要修改的值 B,当且仅当预
期值 A 和内存值 V 相同时,将内存值修改为 B 并返回 true,否则什么都不做并
返回 false。

CAS 操作是基于处理器的 CMPXCHG 汇编指令实现的, JVM 只是封装了汇
编调用。 因此, JVM 中的 CAS 的原子性是处理器保障的。

CAS 缺点

CAS 存在三个问题:
1. ABA 问题
如果一个变量 V 初次读取的时候是 A 值,并且在准备赋值的时候检查到它
仍然是 A 值;如果在这段期间它的值曾经被改成了 B,然后又改回 A,那 CAS 操
作就会误认为它从来没有被修改过。这个漏洞称为 CAS 操作的”ABA”问题。
2. 循环时间长开销大
3. 只能保证一个共享变量的原子操作
解决方案: AtomicMarkableReference、 AtomicStampedReference
AtomicMarkableReference 是利用一个 boolean 标记记录版本是否更改。
AtomicStampedReference 是利用版本戳的形式记录了每次改变以后的版本
号。

cas 具备自旋锁的特征

由于compareAndSet内部是一个不断循环的操作,只有更新成功才会跳出循环,否则会不断调整期望值

缺点 消耗时间

你可能感兴趣的:(java基础)