compare and swap:寄存器A的值和内存M的值进行比较,如果值相同,就把寄存器B和M的值进行交换
更多的时候,不关心寄存器中的数量是啥,更关心内存的数值(变量的值)
CAS相当于是把开了新世界的大门,让咱们不加锁就能保证线程安全!!
基于CAS可以实现很多操作:
- 实现原子类:标准库里提供了AtomInteger类,能够保证++,--的时候线程安全!
基于CAS实现两个线程各自自增5W次
import java.util.concurrent.atomic.AtomicInteger; public class Main1 { //基于CAS实现两个线程各自自增5W次 public static void main(String[] args) throws InterruptedException{ AtomicInteger num=new AtomicInteger(0); //初始化为0 //线程1 Thread t1=new Thread(()->{ for (int i = 0; i < 50000; i++) { //num++ 后置++ num.getAndIncrement(); //++num 前置++ //num.incrementAndGet();前置-- // num.getAndDecrement();后置-- } }); //线程2 Thread t2=new Thread(()->{ for (int i = 0; i < 50000; i++) { num.getAndIncrement(); //后置++ } }); t1.start(); t2.start(); //阻塞等待 t1.join(); t2.join(); //get获取到数值 System.out.println(num.get());//100000 } }
上述代码的运行结果为:
- 实现自旋锁
反复检查当前的锁状态,看是否解开了
实现自旋目的就是为了忙等,就是为了能够最快速的拿到锁!!
CAS还能做其他的很多事,在此便不再展开!!
CAS的aba问题:面试中的经典问题!!
CAS关键是对比内存和寄存器的值,看看是否相同(就是通过这个对比来检测内存是否变过),万一对比的时候是相同的,但是不是没变过,而是a->b->a??此时有一定的概率会出现!!
CAS只能对比值是否相同,不能确定这个值是否中间发生过变化!!(这个事情大部分情况下都没事,但是小部分情况下会出现Bug!!)
如何解决aba问题??
aba关键是值反复横跳(a->b->a),如果约定数据只能单方向变化,那么,问题就迎刃而解了!!(只能增加/只能减少)
但是若需求要求某数值,既能增加又能减少,咋办??
可以引入另外一个版本号变量,约定版本号只能增加(每次修改,都会增加一个版本号)
只要约定版本号,只能递增,就能保持此时不会出现aba反复横跳问题!!以版本号为基准,而不是变量数量为基准了!!