1 什么是CAS?
比较并交换
如果线程的期望值和物理内存的真实值一致,就修改
如果线程的期望值和物理内存的真实值不一致,本次修改失败,需要重新获取主物理内存的真实值。
public class CASDemo {
public static void main(String[] args) {
AtomicInteger atomicInteger = new AtomicInteger(666);
// 获取真实值,并替换为相应的值
boolean b = atomicInteger.compareAndSet(666, 2019);
System.out.println(b); // true
boolean b1 = atomicInteger.compareAndSet(666, 2020);
System.out.println(b1); // false
//getAndIncrement 解决了多线程问题
atomicInteger.getAndIncrement();
}
}
1 new了一个对象,初始值是5 。存在主物理内存中。
2 t1 ,t2分别从主内存中拷贝到自己的工作内存中。
3 t1 改为2019 ,快照值和主主内存的值都是5,允许写回主内存并交换
4 t2 改为1020 ,但此时快照的值5 和主内存的值2019不一致,本次修改失败
总结:
CAS:
如果线程的期望值和物理内存的真实值一致,就修改
如果线程的期望值和物理内存的真实值不一致,本次修改失败,需要重新获取主物理内存的真实值。
2 CAS 底层原理?谈谈对 UnSafe 的理解?
2.1getAndIncrement();
/**
* Atomically increments by one the current value.
*
* @return the previous value
*/
public final int getAndIncrement() {
return unsafe.getAndAddInt(this, valueOffset, 1);
}
2.2 UnSafe 类
public class AtomicInteger extends Number implements java.io.Serializable {
private static final long serialVersionUID = 6214790243416807050L;
// setup to use Unsafe.compareAndSwapInt for updates
private static final Unsafe unsafe = Unsafe.getUnsafe();
private static final long valueOffset;
static {
try {
// 获取下面 value 的地址偏移量
valueOffset = unsafe.objectFieldOffset
(AtomicInteger.class.getDeclaredField("value"));
} catch (Exception ex) { throw new Error(ex); }
}
private volatile int value;
// ...
}
2.3CAS 是什么
。CAS 的全称 Compare-And-Swap,它是一条 CPU 并发。
。它的功能是判断内存某一个位置的值是否为预期,如果是则更改这个值,这个过程就是原子的。
。CAS 并发原体现在 JAVA 语言中就是 sun.misc.Unsafe 类中的各个方法。调用 UnSafe 类中的 CAS 方法,JVM 会帮我们实现出 CAS 汇编指令。这是一种完全依赖硬件的功能,通过它实现了原子操作。由于 CAS 是一种系统源语,源语属于操作系统用语范畴,是由若干条指令组成,用于完成某一个功能的过程,并且原语的执行必须是连续的,在执行的过程中不允许被中断,也就是说 CAS 是一条原子指令,不会造成所谓的数据不一致的问题。
2.4 CAS 的缺点?
。循环时间长开销很大
如果 CAS 失败,会一直尝试,如果 CAS 长时间一直不成功,可能会给 CPU 带来很 大的开销(比如线程数很多,每次比较都是失败,就会一直循环),所以希望是线程数比较小的场景。
。只能保证一个共享变量的原子操作
。对于多个共享变量操作时,循环 CAS 就无法保证操作的原子性。
。引出 ABA 问题