CAS乐观锁原理

1、什么是CAS?

compare and swap也就是比较和交换,他是一条CPU的并发原语。

他在替换内存的某个位置的值时,首先查看内存中的值与预期值是否一致,如果一致,执行替换操作。
这个操作是一个原子性操作。

Java中基于Unsafe的类提供了对CAS的操作的方法,JVM会帮助我们将方法实现CAS汇编指令但是要清楚CAS只是比较和交换,在获取原值的这个操作上,需要你自己实现。

public class AtomicIntegerTest {

    public static AtomicInteger atomicInteger = new AtomicInteger(0);
    public static void main(String[] args) {

        new Thread(() -> {
            for (int i = 0; i < 100; i++) {
                int i1 = atomicInteger.incrementAndGet();
                System.out.println(i1);
            }
        }).start();


        new Thread(() -> {
            for (int i = 0; i < 100; i++) {
                int i1 = atomicInteger.incrementAndGet();
                System.out.println(i1);
            }
        }).start();
    }
}

Doug Lea在CAS的基础上帮助我们实现了一些原子类,其中就包括现在看到的Atomicinteger,还有其他很多原子类.

CAS的缺点:CAS只能保证对一个变量的操作是原子性的,无法实现对多行代码实现原子性。

CAS的问题:
·ABA问题:问题如下,可以引入版本号的方式,来解决ABA的问题。Java中提供了一个类在CAS时,针对各个版本追加版本号的操作。AtomicStampeReference

CAS 线程的ABA问题

初始值为str=A ,此时线程1修改str A 为B ,线程2修改str B为A ,此时线程3看到了还是A,但是此时的A已不是最初的那个A了,此时线程存在ABA问题。

public class AtomicInteger2Test {
    public static void main(String[] args) {
        //初始值
        AtomicReference<String> stringAtomicReference = new AtomicReference<>("A");

        //线程1进行修改
        new Thread(() -> {
            boolean b = stringAtomicReference.compareAndSet("A", "B");
            System.out.println(Thread.currentThread().getName() + ":" + b);
            System.out.println(Thread.currentThread().getName() + ":" + stringAtomicReference.get());
        }, "t1").start();

        //线程2进行修改
        new Thread(() -> {
            boolean b = stringAtomicReference.compareAndSet("B", "A");
            System.out.println(Thread.currentThread().getName() + ":" + b);
            System.out.println(Thread.currentThread().getName() + ":" + stringAtomicReference.get());
        }, "t2").start();


        //线程3进行修改
        new Thread(() -> {
            boolean b = stringAtomicReference.compareAndSet("A", "B");
            System.out.println(Thread.currentThread().getName() + ":" + b);
            System.out.println(Thread.currentThread().getName() + ":" + stringAtomicReference.get());
        },"t3").start();
    }
}

如何进行ABA问题的避免呢?

public class AtomicStampReferenceTest {
    public static void main(String[] args) {
        AtomicStampedReference<String> initVal = new AtomicStampedReference<String>("A",1);

        //线程1进行修改
        new Thread(()->{
            boolean b = initVal.compareAndSet("A", "B", 1, 2);
            System.out.println(Thread.currentThread().getName()+"线程修改结果:"+b);
        },"t1").start();


        //线程2进行修改
        new Thread(()->{
            boolean b = initVal.compareAndSet("B", "A", 2, 3);
            System.out.println(Thread.currentThread().getName()+"线程修改结果:"+b);
        },"t2").start();

        //线程3进行修改
        new Thread(()->{
            boolean b = initVal.compareAndSet("A", "B", 1, 2);
            System.out.println(Thread.currentThread().getName()+"线程修改结果:"+b);
        },"t3").start();
    }
}

相关推荐

  1. 深度解析乐观

    2024-07-23 08:46:06       52 阅读
  2. 乐观与悲观

    2024-07-23 08:46:06       45 阅读
  3. 乐观和悲观

    2024-07-23 08:46:06       38 阅读
  4. 乐观和悲观

    2024-07-23 08:46:06       36 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-23 08:46:06       104 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-23 08:46:06       115 阅读
  3. 在Django里面运行非项目文件

    2024-07-23 08:46:06       94 阅读
  4. Python语言-面向对象

    2024-07-23 08:46:06       100 阅读

热门阅读

  1. stm32 io输入中断

    2024-07-23 08:46:06       30 阅读
  2. pytorch lightning报错all tensors to be on the same device

    2024-07-23 08:46:06       21 阅读
  3. 关于正运动学解机器人手臂算法

    2024-07-23 08:46:06       25 阅读
  4. Torus结构代码实现

    2024-07-23 08:46:06       26 阅读
  5. linux命令-touch-修改文件时间

    2024-07-23 08:46:06       25 阅读
  6. Oracle(17)什么是物化视图(Materialized View)?

    2024-07-23 08:46:06       24 阅读
  7. Electron 和 React 开发桌面应用程序

    2024-07-23 08:46:06       29 阅读
  8. (20240721)无机非金属材料工学(3)混凝土

    2024-07-23 08:46:06       24 阅读
  9. golang长连接的误用

    2024-07-23 08:46:06       24 阅读