19、深入理解CAS
19.1. CAS是什么
CAS : CompareAndSwarp ,比较并交换
package com.interview.concurrent.cas;
import java.util.concurrent.atomic.AtomicInteger;
/**
* @author DDKK.COM 弟弟快看,程序员编程资料站
* @description 描述: compareAndSet 简称 CAS 比较并交换!
* compareAndSet(int expect, int update)
* expect:我期望原来的值是什么,如果是,就更新为update
* @date 2023/2/25 14:46
*/
public class AtomicIntegerDemo {
public static void main(String[] args) {
//参数,初始值设为5
AtomicInteger atomicInteger = new AtomicInteger(5);
System.out.println(atomicInteger.get()); //5
// compareAndSet 简称 CAS 比较并交换!
// compareAndSet(int expect, int update) expect:我期望原来的值是什么,如果是,就更新为update
System.out.println(atomicInteger.compareAndSet(5, 1000)); //true
System.out.println(atomicInteger.compareAndSet(5, 1000));//false
for (int i = 0; i < 10; i++) {
atomicInteger.getAndIncrement();
System.out.println(atomicInteger.get());
}
}
}
19.2. CAS 底层原理
19.2.1. 分析过程
CAS 底层原理?如果知道,谈谈你对UnSafe的理解?
getAndIncrement
分析这个+1是怎么实现的
public final int getAndIncrement() {
return unsafe.getAndAddInt(this, valueOffset, 1);
}
Unsafe 是java出生就自带的
@HotSpotIntrinsicCandidate
public final int getAndAddInt(Object o, long offset, int delta) {
int v;
do {
v = getIntVolatile(o, offset);
} while (!weakCompareAndSetInt(o, offset, v, v + delta));
return v;
}
Unsafe 就是CAS 的核心类 !
JAVA 无法直接操作系统的底层! 而Unsafe 是Java留的后门,可直接操作特定内存中的数据, 方法都是 native 类型,里面的所有的所有方法 ,都可以像C的指针一样直接操作内存!
19.2.2. CAS本质
最后解释CAS 是什么
CAS是一个 CPU的 并发原语!**它的功能就是判断内存中的某个位置的值是否是预期值,如果是更新为自己指定的新值。**这个操作是原子性的,内存级别的,而且是连续的。
CAS彻底解决 数据不一致的问题!
cas 源码分析
Unsafe 类中的 compareAndSwapint,是一个本地方法,该方法的实现位于 unsafe.cpp 中。
具体见unsafe.cpp
UNSAFE_ENTRY(jboolean, Unsafe_CompareAndSetInt(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jint e, jint x)) {
oop p = JNIHandles::resolve(obj);
//获取对象的变量的地址
jint* addr = (jint *)index_oop_from_field_offset_long(p, offset);
//调用Atomic操作
return (jint)(Atomic::cmpxchg(x, addr, e)) == e;
} UNSAFE_END
先去获取一次结果,如果结果和现在不同,就直接返回,因为有其他人修改了;否则会一直尝试去修改。直到成功。
总结
CAS: 比较当前工作内存中的值和主内存中的值,如果相同,则执行操作,否则就一直比较直到值一致为止!
如下示例:
内存值A: 旧的预期值 B , 想修改为 V!
如果A和B相等,就修改为V,如果不相等,就一直比较。直到值相等为止。
19.3. CAS的缺点
CAS的缺点:
1) CPU开销过大
在并发量比较高的情况下,如果许多线程反复尝试更新某一个变量,却又一直更新不成功,循环往复,会给CPU带来很到的压力。
2) 不能保证代码块的原子性
CAS机制所保证的只是一个变量的原子性操作,而不能保证整个代码块的原子性。比如需要保证3个变量共同进行原子性的更新,就不得不使用synchronized了。
3) ABA问题
什么是ABA问题:狸猫换太子
这是CAS机制最大的问题所在。(后面有介绍)