- CAS是什么?Compare-And-Swap 比较并交换,是一条CPU并发原语
它的功能是判断内存某个位置的值是否为预期值,如果是则更改为新的值,这个过程是原子的。CAS在Java中的体现是sun.misc.Unsafe类中的哥哥方法。调用Unsafe类中的CAS方法,JVM会帮我们实现出CAS汇编指令。这是一种完全依赖于硬件的功能,通过它实现原子操作。(因为原语的执行必须是连续的,在执行过程中,不允许被中断,也就是说CAS是一条CPU的原子指令,不会造成数据不一致问题。)
总结:①volatile虽然保证可见(保证使用同一主物理内存变量的线程一直拿到新的值,而不是拿着旧的值得出错误的结果),但会被打断
②CAS是原语,不会被打断,且用volatile保证可见性
③AtomicInteger的方法是调用unsafe的方法的,unsafe是底层运用CAS,所以AtomicInterger既保证可见性,也保证原子性
public class CASDemo {
public static void main(String[] args) {
AtomicInteger atomicInteger = new AtomicInteger(5);
//期望值是5,且atomicInteger确实是5,true,写入2020
System.out.println(atomicInteger.compareAndSet(5, 2020)+"\t current data: "+atomicInteger.get());
//期望值是5,但atomicInteger已经是2020,false,不改变值,还是2020
System.out.println(atomicInteger.compareAndSet(5, 1024)+"\t current data: "+atomicInteger.get());
}
}
输出:
true current data: 2020
false current data: 2020
总结:首先看看主物理内存的值有没有被其他线程回写过,如果物理内存真实值与我期望值一样,我将写入我的更新值;
否则,本次修改失败,只能放弃之前的操作,我们需要重新获得物理内存的真实值,在新的版本上再进行修改,直到成功为止。
比较并交换的源码(Unsafe类里实现的):
public final int getAndAddInt(Object var1, long var2, int var4) {
int var5;
do {
var5 = this.getIntVolatile(var1, var2);
} while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));
return var5;
}
2、为什么用CAS而不用synchronized?
3、CAS底层原理?
答:①自选锁;②UnSafe
Unsafe是CAS的核心类,Java中CAS操作的执行依赖于Unsafe类的方法(看上面源码)就是靠Unsafe来保证原子性。原本Java是要通过本地(native)方法来访问底层系统的,Unsafe、就像一个后门,基于这个类可以直接操作特定内存的数据
Unsafe类中的所有方法都是natice修饰的,也就是说Unsafe类中的方法都直接调用操作系统底层资源执行相应任务