什么是CAS ?
想进大厂 => 必须深入研究底层 理解计算机网络 操作系统
compareAndSet(int expect , int update) : 比较并交换
expect => 期望值
update => 更新值
如果期望值达到了,就更新为update的值,否则就不更新
package com.liu.cas;
import java.util.concurrent.atomic.AtomicInteger;
public class CASDemo {
// CAS compareAndSet : 比较并交换
public static void main(String[] args) {
AtomicInteger atomicInteger = new AtomicInteger(2020);
atomicInteger.compareAndSet(2020, 2021);
System.out.println(atomicInteger.get());
}
}
CAS 是 CPU的并发原语
原子类 AtomicInteger :声明的变量 :Unsafe 类 + VALUE
Java 自身是无法操作内存的;C++可以直接操作内存
因此Java可以通过Unsafe类 调用C++ 底层(native 方法)来间接操作内存
原子类的getAndIncrement() 底层如何实现?
自旋锁 : 通过do{} while() 实现 不停旋转(循环)直到得到了某个值才停止
内存操作 :实现+1 效率很高
最终发现compareAndSet调用的是本地方法 compareAndSetInt()
CAS : Unsafe类 继续深入 即是 :ABA问题!
小结 :
- CAS : 比较当前工作内存中的值和主内存的之,如果这个值是期望的,那么就执行操作,如果不是则一直循环(自旋锁) => 自带原子性 且 不用切换线程状态 提升性能
- 缺点 :
- 循环会耗时
- 一次性只能保证一个共享变量的原子性
- 会导致ABA问题
什么是ABA问题? 狸猫换太子
ABA 问题的过程是当有两个线程 T1 和 T2 从内存中获取到值A,线程 T2 通过某些操作把内存 值修改为B,然后又经过某些操作将值修改为回值A,T2退出。 线程 T1 进行操作的时候 ,使用预期值同内存中的值比较,此时均为A,修改成功退出。 但是此时的A以及不是原先的A了,这就是 ABA 问题,
package com.liu.cas;
import java.util.concurrent.atomic.AtomicInteger;
public class CASDemo {
// CAS compareAndSet : 比较并交换
public static void main(String[] args) {
AtomicInteger atomicInteger = new AtomicInteger(2020);
System.out.println(atomicInteger.compareAndSet(2020, 2021));
System.out.println("=========捣乱线程===============");
System.out.println(atomicInteger.compareAndSet(2021, 2020));
System.out.println(atomicInteger.compareAndSet(2020, 2021));
// System.out.println(atomicInteger.get());
// atomicInteger.getAndIncrement();
System.out.println("=============预期结果=============");
System.out.println(atomicInteger.compareAndSet(2021, 6666));
System.out.println(atomicInteger.get());
}
}
乐观锁? vs 悲观锁?
对于平时写的SQL: 使用乐观锁(默认其他线程没有修改过数据)
悲观锁:必须判断变量值是否被其他线程修改过!