JUC(10)深入理解CAS和ABA

简介: 这篇文章深入探讨了Java中的CAS(Compare-And-Swap,比较并交换)操作,解释了CAS的工作原理、应用场景以及存在的循环耗时、单变量原子性保证和ABA问题等缺点,并介绍了如何使用原子引用和版本号来解决ABA问题。

文章目录

  • 1、CAS
  • 2、原子引用解决ABA问题,版本号。修改后,可以看到

1、CAS

在这里插入图片描述

在这里插入图片描述

package com.cas;

import java.util.concurrent.atomic.AtomicInteger;

/**
 * CAS compareAndSet:比较并交换
 */
public class CASDemo {
    public static void main(String[] args) {
        AtomicInteger atomicInteger = new AtomicInteger(2021);
        /**
         * 期望、更新
         * public final boolean compareAndSet(int expect, int update)
         * 如果期望值达到了,那么就更新,否则,就不更新
         */
        atomicInteger.compareAndSet(2021,2022);
        System.out.println(atomicInteger.get());
    }
}

CAS:比较当前工作内存中的值和主存中的值,如果这个值是期望的,那么执行操作!如果不是、一直循环

缺点:

  • 1、循环会耗时
  • 2、一次性只能保证一个共享变量的原子性
  • 3、存在ABA问题
    ABA问题:狸猫换太子

举例子:A 打算让1变为2.在这个过程中,线程B已经对其进行过修改,从1,到3,再从3,到1。对线程A来讲,好像没啥大的变化。
在这里插入图片描述

package com.cas;

import java.util.concurrent.atomic.AtomicInteger;

public class ABADemo {
    public static void main(String[] args) {
        AtomicInteger atomicInteger = new AtomicInteger(2021);
        /**
         * 期望、更新
         * public final boolean compareAndSet(int expect, int update)
         * 如果期望值达到了,那么就更新,否则,就不更新
         */
        System.out.println(atomicInteger.compareAndSet(2021, 2022));
        System.out.println(atomicInteger.get());

        System.out.println(atomicInteger.compareAndSet(2022, 2021));
        System.out.println(atomicInteger.get());

        System.out.println(atomicInteger.compareAndSet(2021, 6666));
        System.out.println(atomicInteger.get());

    }
}

2、原子引用解决ABA问题,版本号。修改后,可以看到

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

举例子(乐观锁)

package com.cas;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicStampedReference;

/**
 * AtomicStampedReference 注意:如果泛型是一个包装类,注意对象的引用问题
 */
public class AtomicStampedReferenceDemo {
    public static void main(String[] args) {
        AtomicStampedReference<Integer> atomicStampedReference = new AtomicStampedReference<>(66, 1);

        new Thread(()->{
         int stamp = atomicStampedReference.getStamp();//获得版本号
         System.out.println("A===>"+stamp);



            atomicStampedReference.compareAndSet(66,99,atomicStampedReference.getStamp(),atomicStampedReference.getStamp()+1);
            System.out.println("A2==>"+atomicStampedReference.getStamp());

            atomicStampedReference.compareAndSet(99,66,atomicStampedReference.getStamp(),atomicStampedReference.getStamp()+1);
            System.out.println("A3==>"+atomicStampedReference.getStamp());

        },"A").start();

        new Thread(()->{
            int stamp = atomicStampedReference.getStamp();//获得版本号
            System.out.println("B===>"+stamp);

            try {
                TimeUnit.SECONDS.sleep(6);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            atomicStampedReference.compareAndSet(66,6,stamp,stamp+1);
            System.out.println("B1==>"+atomicStampedReference.getStamp());

        },"B").start();
    }
}

测试结果
在这里插入图片描述

相关文章
|
6月前
|
算法 Java
浅谈一下CAS和ABA问题
浅谈一下CAS和ABA问题
70 0
|
1月前
|
安全
【多线程】CAS、ABA问题详解
【多线程】CAS、ABA问题详解
18 0
|
6月前
|
缓存 算法 Java
JUC并发编程之CAS
CAS,即Compare and Swap,是一种并发编程中用于实现多线程环境下的原子操作的技术。它是一种无锁算法,用于解决多线程环境下的数据同步问题。CAS操作包含三个操作数:内存位置V,旧的预期值A和即将要写入的新值B。只有当内存位置的值与旧的预期值A相等时,才会将新值B写入内存位置V,否则不执行任何操作。CAS操作是原子的,保证了多线程环境下的数据一致性和线程安全性。
|
6月前
|
算法
原子操作CAS
原子操作CAS
38 0
|
6月前
详解CAS及ABA问题
详解CAS及ABA问题
102 0
|
Java
面试java并发~(lock、volatile、cas)
面试java并发~(lock、volatile、cas)
60 0
|
安全
CAS和多线程密切相关的东西!
CAS和多线程密切相关的东西!
30 0
|
安全 Java C++
CAS自旋锁到底是什么?为什么能实现线程安全?
本文是博主对多线程学习总结记录,希望对大家有所帮助。
1219 0
CAS自旋锁到底是什么?为什么能实现线程安全?
解决CAS机制中ABA问题的AtomicStampedReference详解
AtomicStampedReference是一个带有时间戳的对象引用,能很好的解决CAS机制中的ABA问题,这篇文章将通过案例对其介绍分析。
299 0
解决CAS机制中ABA问题的AtomicStampedReference详解