首页 > 编程语言 >CAS原子类:AtomicLongArray源码解析

CAS原子类:AtomicLongArray源码解析

时间:2024-09-29 16:51:31浏览次数:7  
标签:AtomicLongArray CAS long public int 源码 scale 数组 final

AtomicLongArray内部维护了一个int类型的数组,需要先复习下数组对象的在内存中的结构,这对接下来对数组类型原子类的理解至关重要。

一、数组对象的内存结构

我们运行以下代码并将数组对象的内存结构通过JOL工具打印出来,关于这部分知识,参考之前的文章:深入理解Java对象结构

public class ArrayTest {
    
    public static void main(String[] args) {
        //打印虚拟机信息
        System.out.println(VM.current().details());
        //十个元素的int数组
        int[] array = new int[]{0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
        //打印内存结构
        System.out.println(ClassLayout.parseInstance(array).toPrintable());
    }
}

输出结果:

image-20240926145450620

整个对象大小是16字节的对象头+40字节的对象体,一共56字节,由于正好是对齐字节数8的倍数,所以没有对齐字节。

问题来了,如果站在Unsafe类的角度上,如何实现快速访问数组中的某个元素?

Unsafe可以基于偏移量的快速访问,也就是说只要告诉Unsafe前边有多少个字节数,它就可以直接定位到需要访问的元素。如果我想访问第1个元素,那前边就只有对象头,那就是16字节;如果我想访问第二个元素,那就是16字节的对象头+4字节的第一个元素,就是20字节;如果我想访问呢第三个元素,那就是16字节的对象头+8字节的两个元素,就是24个字节。。。如果我想访问下标为i的元素,那就是(16+ix4)个字节。

我们知道位移运算要比乘法运算效率高的多,为了效率最大化,可以使用位移运算替代乘法运算,4正好是22满足位移计算替换的要求(热知识:将一个数i向左位移N位,实际上等效于ix2N,所以必须保证第二个乘数是2的幂次方),所以16+ix4可以替换为16+i<<2,没错,在数组类型原子类中,正是使用这种位移的方式快速定位元素的。

二、get方法源码解析

由于源代码比较长,分开一点一点来看,先看get方法:public final int get(int i),说起来你肯定不信,这个方法是这个类最复杂的方法了

public class AtomicIntegerArray {

    //Unsafe类初始化
    private static final Unsafe unsafe = Unsafe.getUnsafe();
    //数组元素的内存偏移量
    private static final int base = unsafe.arrayBaseOffset(int[].class);
    //位移次数
    private static final int shift;
    //通过final保证可见性
    private final int[] array;

    static {
        //确定数组中每个元素的大小,单位字节
        int scale = unsafe.arrayIndexScale(int[].class);
        //确定scale大小是2的幂次方
        if ((scale & (scale - 1)) != 0)
            throw new Error("data type scale not a power of two");
        //确定位移次数,用于后续计算元素的内存偏移量
        shift = 31 - Integer.numberOfLeadingZeros(scale);
    }

    private long checkedByteOffset(int i) {
        if (i < 0 || i >= array.length)
            throw new IndexOutOfBoundsException("index " + i);

        return byteOffset(i);
    }

    //根据数组坐标查询内存偏移量
    private static long byteOffset(int i) {
        return ((long) i << shift) + base;
    }

    //获取某个元素的值
    public final int get(int i) {
        return getRaw(checkedByteOffset(i));
    }

    //调用unsafe方法根据偏移量获取某个方法的值
    private int getRaw(long offset) {
        return unsafe.getIntVolatile(array, offset);
    }
}

上面的整个源代码都是public final int get(int i)方法相关的函数和变量。接下来逐步看下每段代码的意思。

静态代码块

static {
    //确定数组中每个元素的大小,单位字节
    int scale = unsafe.arrayIndexScale(int[].class);
    //确定scale大小是2的幂次方
    if ((scale & (scale - 1)) != 0)
        throw new Error("data type scale not a power of two");
    //确定位移次数,用于后续计算元素的内存偏移量
    shift = 31 - Integer.numberOfLeadingZeros(scale);
}

相关的注释在代码中,不再赘述,主要解答下几个疑问

  • 为什么要验证scale大小是2的幂次方
  • Integer.numberOfLeadingZeros(scale)的函数作用是什么
  • 为什么要用31减去Integer.numberOfLeadingZeros(scale)
  • 最终计算出来的shift值是干什么用的

相信第一次见这段代码的人都和我一样,对这段静态代码块中的每一行代码都有疑问

标签:AtomicLongArray,CAS,long,public,int,源码,scale,数组,final
From: https://www.cnblogs.com/kuangdaoyizhimei/p/18440359

相关文章

  • 基于Springboot在线拍卖系统【附源码+文档】
    ......
  • 从0到1搭建权限管理系统系列四 .net8 中Autofac的使用(附源码)
    说明  该文章是属于OverallAuth2.0系列文章,每周更新一篇该系列文章(从0到1完成系统开发)。   该系统文章,我会尽量说的非常详细,做到不管新手、老手都能看懂。   说明:OverallAuth2.0是一个简单、易懂、功能强大的权限+可视化流程管理系统。友情提醒:本篇文章是属于系......
  • C++ const_cast 和重载
    在4.11.3节(第145页)中我们说过,const_cast在重载函数的情景中最有用。举个例子,回忆6.3.2节(第201页)的shorterstring函数://比较两个string对象的长度,返回较短的那个引用conststring&shorterString(conststring&sl,conststring&s2){returnsl.size()<=s2.size()?......
  • 基于Java+Springboot+Vue开发的大学竞赛报名管理系统源码+开发文章1.3万字
    项目简介该项目是基于Java+Springboot+Vue开发的大学竞赛报名管理系统(前后端分离),这是一项为大学生课程设计作业而开发的项目。该系统旨在帮助大学生学习并掌握Java编程技能,同时锻炼他们的项目设计与开发能力。通过学习基于Java的大学竞赛报名管理系统项目,大学生可以在实践......
  • 基于Java的校园外卖系统设计与实现源码+两万字论文+答辩PPT+开题报告
    又快到了准备毕业设计的时候了,相信大部分宝子们还没有头绪吧。没有关系的,看完本文相信会让你受益匪浅。 一、项目介绍 本系统是面向所有人的外卖点餐系统。系统内的角色分为管理员和前台用户。管理员有权登录管理端进行如员工信息管理、分类、菜品与套餐管理、查看订单详......
  • getBeansOfType源码解析
    org.springframework.beans及org.springframework.context这两个包是SpringIoC容器的基础,其中重要的类有BeanFactory,BeanFactory是IoC容器的核心接口,其职责包括:实例化、定位、配置应用程序中的对象及建立这些对象间的依赖关系。ApplicationContext作为BeanFactory的子类,在Bean管......
  • 2024最新高分源码基于SpringBoot+Vue+uniapp的办事大厅政务预约系统(源码+lw+部署文档
    文章目录前言详细视频演示具体实现截图技术栈后端框架SpringBoot前端框架Vue持久层框架MyBaitsPlus系统测试系统测试目的系统功能测试系统测试结论为什么选择我代码参考数据库参考源码获取前言......
  • 2024最新高分源码基于SpringBoot+Vue+uniapp的网络办公系统(源码+lw+部署文档+讲解等)
    文章目录前言详细视频演示具体实现截图技术栈后端框架SpringBoot前端框架Vue持久层框架MyBaitsPlus系统测试系统测试目的系统功能测试系统测试结论为什么选择我代码参考数据库参考源码获取前言......
  • 2024最新高分源码基于SpringBoot+Vue+uniapp的贫困认定管理平台(源码+lw+部署文档+讲
    文章目录前言详细视频演示具体实现截图技术栈后端框架SpringBoot前端框架Vue持久层框架MyBaitsPlus系统测试系统测试目的系统功能测试系统测试结论为什么选择我代码参考数据库参考源码获取前言......
  • Pbootcms模板源码如何做好防护
    为了提高PBootCMS模板的安全性,以下是一些详细的防护措施和步骤。这些措施可以有效减少网站被攻击的风险。防护措施升级后台到最新版本:确保PBootCMS后台已升级到最新版本,以获得最新的安全补丁和功能改进。重命名关键文件夹:更改关键文件夹名称,使其不易被猜测。......