前言
CAS的全称是:比较并交换(Compare And Swap)。在CAS中,有这样三个值:
V:要更新的变量(var) E:预期值(expected) N:新值(new) 比较并交换的过程如下:
判断V是否等于E,如果等于,将V的值设置为N;如果不等,说明已经有其它线程更新了V,则当前线程放弃更新,什么都不做。
所以这里的预期值E本质上指的是“旧值”
一、锁? CAS?
CAS 相当于一个乐观锁,比较后,根据比较结果,赋值; 常见的乐观锁使用场景: 数据库
二、juc--java.util.concurrent
1.CAS思想的落地
CAS的实现
2 ABA问题出现
所谓ABA问题,就是一个值原来是A,变成了B,又变回了A。这个时候使用CAS是检查不出变化的,但实际上却被更新了两次
通过版本号,或者时间戳来解决 AtomicStampedReference
3 可以解决的问题
我们之前计算的时候,用基本类型作为计算,不加锁的时候,会导致计算结果错误,当用了上述的CAS类之后,再做计算就不会有问题了,
代码语言:javascript复制@Data
public class 多线程问题 implements Runnable {
//public static int num = 0;
//private synchronized void add() {
// for (int i = 0; i < 500; i ) {
// num ;
// }
//}
//public volatile int num = 0;
AtomicInteger num = new AtomicInteger(0);
private void add() {
for (int i = 0; i < 500; i ) {
num.getAndIncrement();
//num ;
}
}
@Override
public void run() {
add();
}
public static void main(String[] args) {
for (int i = 0; i < 1000; i ) {
多线程问题 pro = new 多线程问题();
Thread thread = new Thread(pro);
thread.setName("第一个线程");
Thread thread1 = new Thread(pro);
thread1.setName("第二个线程");
thread1.start();
thread.start();
while (Thread.activeCount() > 1) {
Thread.yield();
}
System.out.println(pro.num.get());
//System.out.println(pro.getNum());
}
}
}
4 缺点
当CAS失败后,通常是抛出异常或者自旋来解决,那么如果一直失败,自旋的方式就会给cpu造成非常大的开销;
总结
CAS是一个理论,理论的核心就是我要修改的值,是不是没有被其他线程修改过,判断为true,那么我不应该修改,判断为flase 那么我可以对其进行修改;