当前位置: 首页 > news >正文

CAS - 从AtomicInteger窥探CAS

        Unsafe类是CAS的核心,由于Java方法无法直接访问底层,需要通过本地方法(native)来实现,Unsafe类相当于一个桥梁。基于Unsafe类,可以直接操作特定的内存数据。

        我们从上一篇说CAS基本原理的时候,有说到一个“资源”被100个线程每个线程累加100次,最终得到10000,该“资源”我们使用AtomicInteger来模拟的。这篇我们就从AtomicInteger更加深入探究CAS。

        

AtomicInteger的getAndIncrement()方法

    /*** Atomically increments by one the current value.** @return the previous value*/public final int getAndIncrement() {return unsafe.getAndAddInt(this, valueOffset, 1);}

        AtomicInteger的getAndIncrement()方法调用的是Unsafe类中的getAndAddInt()方法,其中的参数valueOffset是通过Unsafe实例的获取到当前AtomicInteger这个对象的value属性的内存偏移地址。

Unsafe的getAndAddInt()方法

public final int getAndAddInt(Object var1, long var2, int var4) {int var5;do {var5 = this.getIntVolatile(var1, var2);} while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));return var5;}

        参数var1就是当前需要Unsafe类操作的对象,在当前案例中就是AtomicInteger的一个实例。var2则是当前AtomicInteger实例(也就是var1)的value这个属性的变量的内存地址偏移量。var4就是案例中需要累加的值(案例中是1)。

        接下来是一个 do{ } while()循环,首先通过Unsafe类的getIntVolatile()方法(native方法)拿到当前操作的AtomicInteger的实例中的value属性的值,在使用Unsafe类的compareAndSwapInt()方法(native方法),将当前操作的AtomicInteger的实例中的value属性的原值和新值进行CAS。如果没有交换成功就一直重复上面的动作,如果交换成功就跳出当前循环。

      

AtomicInteger的get()方法

    /*** Gets the current value.** @return the current value*/public final int get() {return value;}

        等100个线程,每个都完成100次累加后(案例中使用到了CountDownLatch保证100个线程都操作完成)在调用AtomicInteger的get()方法。我们发现AtomicInteger的get()方法获取的就是value这个值,value属性是由volatile修饰的(在多线程环境下保证其可见性)。

        最终我们发现AtomicInteger实现多线程并发保证线程安全,是通CAS(compare and swap)+volatile来实现的,从而避免synchronized的高开销,提高执行效率。

http://www.lryc.cn/news/109282.html

相关文章:

  • micro-ros IMU ML 代码
  • 二十三种设计模式第二十四篇--访问者模式(完结撒花)
  • 月报总结|Moonbeam 7月份大事一览
  • 【2023.8】docker一键部署wvp-GB28181-pro和ZLMediaKit过程全记录
  • 【2023】字节跳动 10 日心动计划——第四关
  • 数据库与数据仓库的区别及关系
  • Emacs之设置行号前景颜色(字体颜色)/背景颜色/光标颜色/背景透明度(一百二十七)
  • 【hive经典指标,离线数仓指标,ADS层指标分析】最近7日内连续3日下单用户数
  • 线上java程序CPU及内存占用过高问题排查总结
  • c高级:day3
  • Java检查值是否存在于数组中的3种方法
  • python 连接oracle pandas以简化excel的编写和数据操作
  • Kubernetes高可用集群二进制部署(三)部署api-server
  • 【网络|TCP】三次握手、四次握手
  • 刷题笔记 day7
  • Tuxera NTFS2023Mac强大的Mac读写工具
  • ARM64 常见汇编指令学习 11 -- ARM 汇编宏 .macro 的学习
  • 数据库的分库分表
  • [Docker实现测试部署CI/CD----相关服务器的安装配置(2)]
  • LC-980. 不同路径 III(回溯)
  • 软件测试缺陷报告
  • vue js-table2excel 导出excel 可带多张图片
  • HTML 基础标签
  • Nginx使用proxy_cache指令设置反向代理缓存静态资源
  • React安装ant design组件库,并使用
  • Leetcode | 有效的括号、最长有效括号
  • 思科模拟器配置静态路由(下一跳使用IP)
  • MyBatis -- 执行流程
  • springboot背诵
  • WebGL: 几个入门例子