compare and swap:寄存器A的值和内存M的值进行比较,如果值相同,就把寄存器B和M的值进行交换
更多的时候,不关心寄存器中的数量是啥,更关心内存的数值(变量的值)
CAS相当于是把开了新世界的大门,让咱们不加锁就能保证线程安全!!
基于CAS可以实现很多操作:
基于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反复横跳问题!!以版本号为基准,而不是变量数量为基准了!!