1.什么是CAS
CAS(compare and swap),字面意思是比较与交换,比较与交换的是内存和寄存器。
比如说现在我有两个寄存器A和B,还有一个内存M。CAS(M,A,B)的含义就是比较M和A的值是不是相同,如果相同则将B的值赋值给M,并且返回true;如果不同就返回false。CAS本质上一个cpu指令(原子操作) =》操作系统将其封装成一个api =》JVM也将其封装,提供成一个api =》程序员调用
优点:保证线程安全的同时,还避免了线程阻塞
缺点:(1)代码繁琐,不容易理解
(2)只能在一些特定的场景下使用,没有synchronized使用的普适
2.基于CAS实现原子类
比如int 对于++操作不是原子的,它需要(load,add,save),而AtomicInteger类是基于CAS对int进行了封装,它对于++操作是原子的。
public class Test13 {
private static AtomicInteger count = new AtomicInteger();
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(()->{
for (int i = 0; i < 50000; i++) {
count.getAndIncrement();//count++
// count.incrementAndGet();++count
// count.getAndDecrement();count--
// count.decrementAndGet();--count
}
});
Thread t2 = new Thread(()->{
for (int i = 0; i < 50000; i++) {
count.getAndIncrement();
}
});
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println(count.get());
}
}
3.CAS引发的ABA问题
那什么是ABA问题?如下图所示
这显然是不合理的,但是上述情况发生的概率很低,所以CAS在通常情况下不会有什么bug,但是有可能在极端情况下出现ABA问题。
4.解决ABA问题
那我们要解决ABA问题,只要再设置一个变量:版本号。每次修改的时候让版本号自增,CAS每次去判断版本号有没有改变,没有改变就注定没有别的线程穿插。