21.深入理解CAS
什么是CAS compareAndSet
大厂你必须要深入研究底层!
操作系统、计算机网络原理
Unsafe类 getAndIncrement 底层 相当于num++
CAS :比较当前工作内存中的值和主内存中的值,如果这个值是期望的,那么则执行操作!如果不是就一直循环!
package cas;
import java.util.concurrent.atomic.AtomicInteger;
//CAS
public class CASDemo {
public static void main(String[] args) {
AtomicInteger atomicInteger = new AtomicInteger(2020);
//期望
// public final boolean compareAndSet(int expect, int update)
//如果我期望的值达到了,就更新,否则 就不更新 CAS是CPU的并发原语
System.out.println(atomicInteger.compareAndSet(2020,2021));//true
System.out.println(atomicInteger.get());//2021
System.out.println(atomicInteger.compareAndSet(2020,2021));//false
System.out.println(atomicInteger.get());//2021
}
}
缺点∶
1、循环会耗时
2.一次性只能保证一个共享变量的原子性
3、ABA问题
CAS: ABA问题 (狸猫换太子)
22.原子引用解决ABA问题
前言
package cas;
import java.util.concurrent.atomic.AtomicInteger;
//CAS
public class CASDemo {
public static void main(String[] args) {
AtomicInteger atomicInteger = new AtomicInteger(2020);
//捣乱的线程
System.out.println(atomicInteger.compareAndSet(2020,2021));//true
System.out.println(atomicInteger.get());//2021
System.out.println(atomicInteger.compareAndSet(2021,2020));//true
System.out.println(atomicInteger.get());//2020
//期望的线程
System.out.println(atomicInteger.compareAndSet(2020,6666));//true
System.out.println(atomicInteger.get());//6666
}
}
//我希望数据被改动我知道
解决ABA问题 ,引入原子引用 (可以联想一下乐观锁)
带版本号的原子操作!
Integer使用了对象缓存机制,默认范围是-128~127,推荐使用静态工厂方法valueof获取对象实例,而不是new ,因为valueof使用缓存,而new一定会创建新的对象分配新的内存空间;
package cas;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicStampedReference;
//CAS
public class CASDemo {
public static void main(String[] args) {
//AtomicStampedReference 如果泛型是一个包装类吗,注意对象的引用问题
// 注意Integer -127~128
//正常在业务操作,比较的是一个个对象 User
AtomicStampedReference<Integer> atomicStampedReference = new AtomicStampedReference<>(1, 1);
new Thread(()->{
int stamp = atomicStampedReference.getStamp();//获得版本号
System.out.println("a1---->"+stamp);//a1---->1
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
atomicStampedReference.compareAndSet(1, 2,
atomicStampedReference.getStamp(), atomicStampedReference.getStamp() + 1
);
System.out.println("a2---->"+atomicStampedReference.getStamp());//a2---->2
System.out.println(atomicStampedReference.compareAndSet(2, 1,
atomicStampedReference.getStamp(), atomicStampedReference.getStamp() + 1
));//true
System.out.println("a3---->"+atomicStampedReference.getStamp());//a3---->3
},"a").start();
new Thread(()->{
int stamp = atomicStampedReference.getStamp();//获得版本号
System.out.println("b1---->"+stamp);//b1---->1
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(atomicStampedReference.compareAndSet(1, 6,
stamp, stamp + 1
));//false
System.out.println("b2----->"+atomicStampedReference.getStamp());//b2----->3
},"b").start();
}
}