前言
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类之后,再做计算就不会有问题了,
@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 那么我可以对其进行修改;