Java 乐观锁 CAS学习

发布时间:2024年01月10日

在多线程的环境中很多地方需要锁,主要分为悲观锁和乐观锁,悲观锁性能不佳,通常使用乐观锁,java有几种实现乐观锁的机制简单记录一下:

CAS算法(Compare And Swap):CAS算法是一种乐观锁的实现方式,它可以在并发场景下保证线程安全。CAS算法包含了三个参数,分别是内存值V、旧的预期值A和要修改的新值B。当且仅当内存值V与旧的预期值A相同时,CAS才会将内存值V修改为新值B,否则CAS不会修改内存值V。Java中的AtomicInteger、AtomicBoolean和AtomicLong等原子类就是CAS的典型应用。

CAS是JDK提供的非阻塞原子性操作,它通过硬件保证了比较-更新的原子性。
它是非阻塞的且自身原子性,也就是说这玩意效率更高且通过硬件保证,说明这玩意更可靠。

CAS是一条CPU的原子指令(cmpxchg指令),不会造成所谓的数据不一致问题,Unsafe提供的CAS方法(如compareAndSwapXXX)底层实现即为CPU指令cmpxchg。
执行cmpxchg指令的时候,会判断当前系统是否为多核系统,如果是就给总线加锁,只有一个线程会对总线加锁成功,加锁成功之后会执行cas操作,也就是说CAS的原子性实际上是CPU实现的, 其实在这一点上还是有排他锁的,只是比起用synchronized, 这里的排他时间要短的多, 所以在多线程情况下性能会比较好。

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

        System.out.println(atomicInteger.compareAndSet(10,20)+"\t"+atomicInteger.get());
        System.out.println(atomicInteger.compareAndSet(5, 25)+"\t"+atomicInteger.get());
    }

跟进源码compareAndSet方法

    /**
     * Atomically sets the value to the given updated value
     * if the current value {@code ==} the expected value.
     *
     * @param expect the expected value
     * @param update the new value
     * @return {@code true} if successful. False return indicates that
     * the actual value was not equal to the expected value.
     */
    public final boolean compareAndSet(int expect, int update) {
        return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
    }

unsafe.compareAndSwapInt方法 是个unsafe方法说明是底层方法了

 public final native boolean compareAndSwapInt(Object var1, long var2, int var4, int var5);

这里只跟到native方法了,是CAS的核心类,由于Java方法无法直接访问底层系统,需要通过本地(native)方法来访问,Unsafe相当于一个后门,基于该类可以直接操作特定内存的数据。Unsafe类存在于sun.misc包中,其内部方法操作可以像C的指针一样直接操作内存,因为Java中CAS操作的执行依赖于Unsafe类的方法。

CAS并发原语体现在JAVA语言中就是sun.misc.Unsafe类中的各个方法。调用UnSafe类中的CAS方法,JVM会帮我们实现出CAS汇编指令。这是一种完全依赖于硬件的功能,通过它实现了原子操作。再次强调,由于CAS是一种系统原语,原语属于操作系统用语范畴,是由若干条指令组成的,用于完成某个功能的一个过程,并且原语的执行必须是连续的,在执行过程中不允许被中断,也就是说CAS是一条CPU的原子指令,不会造成所谓的数据不一致问题。

比较要更新变量的值V和预期值E(compare),相等才会将V的值设为新值N(swap)如果不相等自旋再来。

文章参考:

源码级别的讲解JAVA 中的CAS_cas源码-CSDN博客

文章来源:https://blog.csdn.net/airyearth/article/details/135494418
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。