深入理解JUC:第二章:CAS:CompareAndSwap底层原理

CAS机制解析
本文深入解析了CAS(CompareAndSwap)机制,介绍了其在多线程环境下如何实现变量的比较与交换,确保操作的原子性。通过示例代码展示了AtomicInteger类的使用,以及CAS在解决原子性问题上的应用。同时,文章探讨了CAS的潜在缺点和引出的ABA问题。

CAS是什么?

CAS是CompareAndSwap的缩写,作用是比较与交换。

线程对变量的读取赋值等操作,要先将变量从主内存拷贝自己线程的工作内存空间,在工作内存中进行操作,操作完成后再将变量写回主内存

package com.javaliao.backstage;
import java.util.concurrent.atomic.AtomicInteger;

public class Demo {
    //主线程main,程序入口
    public static void main(String[] args) {
        //原子类整型,在主内存中创建这个对象给初始值为5,默认初始值为0
        AtomicInteger atomicInteger = new AtomicInteger(5);
        //当线程中的工作内存要写回主内存时,拿第一个参数作为期望值和主内存中的值进行比较,如果期望值和主内存中的值相同都为5,更新值主内存中的值为2019
        System.out.println(atomicInteger.compareAndSet(5, 2019)+"\t : "+ atomicInteger.get());

        //线程a
        new Thread(()->{
        //现在主内存中对象的值已经为2019了,期望值为5,和主内存中对象的值不一样,无法将1024写回主内存
        System.out.println(atomicInteger.compareAndSet(5, 1024)+"\t : "+ atomicInteger.get());
        },"a").start();
        
    }
}

控制台:

 这就是为什么我上一章讲的使用AtomicInteger可以解决原子性,因为他在写回主内存时会有一个比较并交互。

AtomicInteger atomicInteger = new AtomicInteger();//默认初始值为0
atomicInteger.getAndIncrement();//加一的操作

调用的getAndIncrement()方法:

public class AtomicInteger extends Number implements java.io.Serializable {
    private static final long serialVersionUID = 6214790243416807050L;

    // setup to use Unsafe.compareAndSwapInt for updates
    private static final Unsafe unsafe = Unsafe.getUnsafe();
    private static final long valueOffset;

    static {
        try {
            //通过objectFieldOffset方法获取内存地址或者说是内存偏移量
            valueOffset = unsafe.objectFieldOffset
                (AtomicInteger.class.getDeclaredField("value"));
        } catch (Exception ex) { throw new Error(ex); }
    }

    private volatile int value;
 
    public final int getAndIncrement() {
        //this是当前对象,valueOffset是内存地址,1是写死的value值
        return unsafe.getAndAddInt(this, valueOffset, 1);
    }

可以看到方法体内又通过调用Unsafe类中的getAndAddInt()方法

源码分析:

//获取当前对象的地址值,var1是这个对象,var2的内存地址,相当于当前线程先从主内存中拷贝变量的值到自己的工作内存中var5就是工作内存中的变量值
var5 = this.getIntVolatile(var1, var2)
//调用CAS方法类型是Int类型的,当前对象(var1)的地址的值(var2的值)和期望值(var5)相同,就将更新值(var5+var4)写回主内存
this.compareAndSwapInt(var1, var2, var5, var5 + var4)
//只有比较成功才可以写回

 

还想了解compareAndSwapInt方法的可以看下图:

而Unsafe类是jdk中rt.jar包下的

小总结:

CAS有什么缺点?

第一个缺点:

第二个缺点:

第三个缺点:

引出来的ABA问题:只管结果,不管过程

 

 

 

 

评论 33
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Java程序员廖志伟

赏我包辣条呗

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值