1. 什么是CAS?
只对一个变量,首先比较它的内存值与某个期望值是否相同,如果相同,就给它赋一个新值。原子操作。
2. JAVA中CAS实现
JAVA中CAS是由UnSafe类提供。有3种见下图
一看native方法就很明显,这是由虚拟机提供的实现。虚拟机源码就算了(能力有限),但是看方法入参: 对象实例、内存偏移量、字段期望值、字段新值。
很明显该方法是获取指定对象实例,根据相应偏移量找到字段,执行 CAS 操作。
3.CAS有什么缺陷
- 自旋 CAS 长时间地不成功,则会给 CPU 带来非常大的开销
- 只能保证一个共享变量原子操作
- ABA 问题
tips: ABA问题怎么解决呢
-
1.ABA问题是什么意思?
ABA问题就是如果有多个线程对一个原子类进行操作的时候, 某个线程在短时间内将原子类的值A修改为B,又马上将其修改为A, 之后其他线程还是会修改成功。
考虑到文字太过惨白,上一个例子吧。。。
public static void main(String[] args) {
AtomicInteger num = new AtomicInteger(1);
Thread first = new Thread(() -> {
System.out.println("first开始执行");
int expect = num.get();
System.out.println("first取得期望值" + expect);
LockSupport.parkNanos(1000000000L);
System.out.println("first-1 "+num.compareAndSet(expect, 4));
});
Thread second = new Thread(() -> {
System.out.println("second开始执行");
int expect = num.get();
System.out.println("second取得期望值" + expect);
System.out.println("second-1 "+num.compareAndSet(expect, 4));
expect = num.get();
System.out.println("second取得期望值" + expect);
System.out.println("second-2 "+num.compareAndSet(expect, 1));
});
first.start();
second.start();
}
输出结果:
first开始执行
first取得期望值1
second开始执行
second取得期望值1
second-1 true
second取得期望值4
second-2 true
first-1 true
-
2.怎么解决?
java中AtomicStampedReference<V>类, 可以解决这种问题。原理就是增加一个版本号,每次改一次数据,版本号就会进行累加。