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


    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)+"	 : "+ atomicInteger.get());
    
            //线程a
            new Thread(()->{
            //现在主内存中对象的值已经为2019了,期望值为5,和主内存中对象的值不一样,无法将1024写回主内存
            System.out.println(atomicInteger.compareAndSet(5, 1024)+"	 : "+ 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问题:只管结果,不管过程

  • 相关阅读:
    数据库注意事项
    SQL函数
    2019 SDN阅读作业(2)
    2019 SDN上机第五次作业
    2019 SDN上机第四次作业
    2019 SDN阅读作业
    2019 SDN上机第三次作业
    mysql使用记录
    2019 SDN上机第二次作业
    2019 SDN上机第一次作业
  • 原文地址:https://www.cnblogs.com/javawxid/p/12811915.html
Copyright © 2020-2023  润新知