AtomicLong、AtomicLongArray、AtomicLongFieldUpdater 深入源码解析

本文主要是介绍AtomicLong、AtomicLongArray、AtomicLongFieldUpdater 深入源码解析,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

  本篇主要对AtomicLong、AtomicLongArray、AtomicLongFieldUpdater进行讲解,本博已经对AtomicInteger、AtomicIntegerArray、AtomicIntegerFieldUpdater源码进行了深入解析。其实这几个类原理都是类似的,不同的是针对的操作数据类型有差异。

  演示示例:

  可以参考《AtomicBoolean 完全源码解析》、《AtomicInteger 完全源码解析》、《AtomicIntegerArray 深入源码解析》、《AtomicIntegerFieldUpdater 深入源码解析》序列文章。

  首先,新建一个Thread类,用于模拟多线程环境:

package com.securitit.serialize.atomics;import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicLongArray;
import java.util.concurrent.atomic.AtomicLongFieldUpdater;public class AtomicLongThread extends Thread {// AtomicLong实例.private AtomicLong atomicLong;// AtomicLongArray实例.private AtomicLongArray atomicLongArray;// AtomicLongFieldUpdater实例.private AtomicLongFieldUpdater<AtomicLongFieldUpdaterBean> atomicLongFieldUpdater;// AtomicLongFieldUpdaterBean实例.private AtomicLongFieldUpdaterBean atomicLongFieldUpdaterBean;// CountDownLatch可以进行线程计数,到达指定计数时,可唤醒调用await方法的线程.private CountDownLatch countDownLatch;public AtomicLongThread(AtomicLong atomicLong, AtomicLongArray atomicLongArray,AtomicLongFieldUpdater<AtomicLongFieldUpdaterBean> atomicLongFieldUpdater,AtomicLongFieldUpdaterBean atomicLongFieldUpdaterBean, CountDownLatch countDownLatch) {this.atomicLong = atomicLong;this.atomicLongArray = atomicLongArray;this.atomicLongFieldUpdater = atomicLongFieldUpdater;this.atomicLongFieldUpdaterBean = atomicLongFieldUpdaterBean;this.countDownLatch = countDownLatch;}@Overridepublic void run() {// 对AtomicLong变量进行累加.atomicLong.incrementAndGet();// 对AtomicLongArray指定索引位置的值进行累加.for (int index = 0; index < atomicLongArray.length(); index++) {atomicLongArray.incrementAndGet(index);}// 对AtomicLongFieldUpdater实例变量进行累加.if(atomicLongFieldUpdater.compareAndSet(atomicLongFieldUpdaterBean, 100L, 200L)) {System.out.println("AtomicLongFieldUpdater 更新成功.");} else {System.out.println("AtomicLongFieldUpdater 更新失败.");}countDownLatch.countDown();}}

  然后,为AtomicLongFieldUpdater测试新建Bean类,类中只包含一个counter属性:

package com.securitit.serialize.atomics;public class AtomicLongFieldUpdaterBean {// 内部计数器.public volatile long counter = 100;public long getCounter() {return counter;}public void setCounter(long counter) {this.counter = counter;}}

  最后,是测试类,在开启多线程操作AtomicLong、AtomicLongArray、AtomicArrayFieldUpdater,以模拟多线程环境:

package com.securitit.serialize.atomics;import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicIntegerArray;
import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicLongArray;
import java.util.concurrent.atomic.AtomicLongFieldUpdater;public class AtomicLongTester {// AtomicLong实例.private static AtomicLong atomicLong;// AtomicLongArray实例.private static AtomicLongArray atomicLongArray;// AtomicLongFieldUpdater实例.private static AtomicLongFieldUpdater<AtomicLongFieldUpdaterBean> atomicLongFieldUpdater;// AtomicLongFieldUpdaterBean实例.private static AtomicLongFieldUpdaterBean atomicLongFieldUpdaterBean;// CountDownLatch可以进行线程计数,到达指定计数时,可唤醒调用await方法的线程.private static CountDownLatch countDownLatch = new CountDownLatch(4);public static void main(String[] args) throws Exception {// 初始化AtomicLong实例.atomicLong = new AtomicLong(100L);// 初始化AtomicLongArray实例.atomicLongArray = new AtomicLongArray(10);// 初始化AtomicLongArray实例数组内部值.for (int index = 0; index < atomicLongArray.length(); index++) {// 用当前索引作为值.atomicLongArray.set(index, index);}// 初始化AtomicLongFieldUpdater实例.atomicLongFieldUpdater = AtomicLongFieldUpdater.newUpdater(AtomicLongFieldUpdaterBean.class, "counter");// 初始化AtomicLongFieldUpdaterBean实例.atomicLongFieldUpdaterBean = new AtomicLongFieldUpdaterBean();atomicLongFieldUpdaterBean.setCounter(100L);// 启动多线程测试.new AtomicLongThread(atomicLong, atomicLongArray, atomicLongFieldUpdater, atomicLongFieldUpdaterBean,countDownLatch).start();new AtomicLongThread(atomicLong, atomicLongArray, atomicLongFieldUpdater, atomicLongFieldUpdaterBean,countDownLatch).start();new AtomicLongThread(atomicLong, atomicLongArray, atomicLongFieldUpdater, atomicLongFieldUpdaterBean,countDownLatch).start();new AtomicLongThread(atomicLong, atomicLongArray, atomicLongFieldUpdater, atomicLongFieldUpdaterBean,countDownLatch).start();// 等待所有线程执行完毕.countDownLatch.await();// 输出AtomicLong的值.System.out.println("AtomicLong:" + atomicLong.get());// 输出AtomicLongArray数值.for (int index = 0; index < atomicLongArray.length(); index++) {if (atomicLongArray.get(index) != index + 4) {System.out.println("数据计算出现问题.");}}}}

  输出结果:

AtomicLongFieldUpdater 更新失败.
AtomicLongFieldUpdater 更新成功.
AtomicLongFieldUpdater 更新失败.
AtomicLongFieldUpdater 更新失败.
AtomicLong:104

  从结果可以看出:

  · AtomicLong在4个线程中被正确增加到4。

  · AtomicLongArray未打印异常日志,说明已更新成功,若想确认,可以将atomicLongArray每一项打印出来确认。

  · AtomicLongFieldUpdater在4个线程中,只有一个线程将值由100L修改为200L,其他线程执行CAS过程中,compare失败。

  源码分析:

  实现基础:

  AtomicLong:

// long类型内存偏移位置.
private static final long valueOffset;
// 记录VM是否支持长整型的无锁CAS操作.
// 虽然Unsafe类的compareAndSwapLong方法在两种情况下均有效.
static final boolean VM_SUPPORTS_LONG_CAS = VMSupportsCS8();
// 数据存储变量.
private volatile long value;

  AtomicLongArray:

// 表示内存中int[]的初始地址.
private static final int base = unsafe.arrayBaseOffset(long[].class);
// int[]数组中元素位移个数.
private static final int shift;
// 用来存储真实int[]数组的变量.
private final long[] array;

  AtomicLongFieldUpdater:

public static <U> AtomicLongFieldUpdater<U> newUpdater(Class<U> tclass, String fieldName){Class<?> caller = Reflection.getCallerClass();if (AtomicLong.VM_SUPPORTS_LONG_CAS)return new CASUpdater<U>(tclass, fieldName, caller);elsereturn new LockedUpdater<U>(tclass, fieldName, caller);
}

  AtomicLongFieldUpdater是一个abstract类,内置了两个静态内部类:CASUpdater和LockedUpdater,若VM支持long类型的CAS操作,则使用CASUpdater进行数据操作;若VM不支持long类型的CAS操作,则使用LockedUpdater(即synchronized)进行数据操作,保证多线程环境下数据安全性。

  基本方法:

  AtomicLong:

// 获取long的值.
public final long get();
// 设置long的值.
public final void set(long newValue);
// 延迟设置long的值.
public final void lazySet(long newValue);
// 先取值,再修改.
public final long getAndSet(long newValue);
// 依赖CAS,进行赋值操作.
public final boolean compareAndSet(long expect, long update);
// 依赖CAS,进行赋值操作.
public final boolean weakCompareAndSet(long expect, long update);
// 先取值,再自增.
public final long getAndIncrement();
// 先取值,再自减.
public final long getAndDecrement();
// 先取值,再原值加上delta.
public final long getAndAdd(long delta);
// 先自增,再取值.  
public final long incrementAndGet();
// 先自减,再取值.
public final long decrementAndGet();
// 先原值加上delta,再取值.
public final long addAndGet(long delta);
// 先取值,再修改当前原值.
public final long getAndUpdate(LongUnaryOperator updateFunction);
// 先修当前原值,再取值.
public final long updateAndGet(LongUnaryOperator updateFunction);
// 使用LongBinaryOperator对当前值和第一个参数进行计算,并更新当前值.
public final long getAndAccumulate(long x, LongBinaryOperator accumulatorFunction);
// 使用LongBinaryOperator对当前值和第一个参数进行计算,并更新当前值.
public final long accumulateAndGet(long x, LongBinaryOperator accumulatorFunction);
// 按int类型取值.
public int intValue();
// 按long类型取值.
public long longValue();
// 按float类型取值.
public float floatValue();
// 按double类型取值.
public double doubleValue();

  AtomicLongArray:

// 数组内容长度.
public final int length();
// 取得指定索引位置的值.
public final long get(int i);
// 设置指定索引位置的值.
public final void set(int i, long newValue);
// 延迟设置指定索引位置的值.
public final void lazySet(int i, long newValue);
// 先取值,再修改.
public final long getAndSet(int i, long newValue);
// 依赖CAS,进行比较替换.
public final boolean compareAndSet(int i, long expect, long update);
// 依赖CAS,进行比较替换.
public final boolean weakCompareAndSet(int i, long expect, long update);
// 先取值,再自增.
public final long getAndIncrement(int i);
// 先取值,再自减.
public final long getAndDecrement(int i);
// 先取值,原值加上delta.
public final long getAndAdd(int i, long delta);
// 先自增,再取值.
public final long incrementAndGet(int i);
// 先自减,再取值.
public final long decrementAndGet(int i);
// 先原值加delta,再取值.
public long addAndGet(int i, long delta);
// 先取值,再修改当前原值.
public final long getAndUpdate(int i, LongUnaryOperator updateFunction);
// 先修当前原值,再取值.
public final long updateAndGet(int i, LongUnaryOperator updateFunction);
// 使用LongBinaryOperator对当前值和第一个参数进行计算,并更新当前值.
public final long getAndAccumulate(int i, long x, LongBinaryOperator accumulatorFunction);
// 使用LongBinaryOperator对当前值和第一个参数进行计算,并更新当前值.
public final long accumulateAndGet(int i, long x, LongBinaryOperator accumulatorFunction);

  AtomicLongFieldUpdater:

// 依赖CAS,进行比较替换.
public abstract boolean compareAndSet(T obj, long expect, long update);
// 依赖CAS,进行比较替换.
public abstract boolean weakCompareAndSet(T obj, long expect, long update);
// 设置值.
public abstract void set(T obj, long newValue);
// 延迟设置值.
public abstract void lazySet(T obj, long newValue);
// 取值.
public abstract long get(T obj);
// 先取值,再修改.
public long getAndSet(T obj, long newValue);
// 先取值,再自增.
public long getAndIncrement(T obj);
// 先取值,再自减.
public long getAndDecrement(T obj);
// 先取值,再原值加上delta.
public long getAndAdd(T obj, long delta);
// 先自增,再取值.
public long incrementAndGet(T obj);
// 先自减,再取值.
public long decrementAndGet(T obj);
// 先原值加上delta,再取值.
public long addAndGet(T obj, long delta);
// 先取值,再修改当前原值.
public final long getAndUpdate(T obj, LongUnaryOperator updateFunction);
// 先修当前原值,再取值.
public final long updateAndGet(T obj, LongUnaryOperator updateFunction);
// 使用LongBinaryOperator对当前值和第一个参数进行计算,并更新当前值.
public final long getAndAccumulate(T obj, long x, LongBinaryOperator accumulatorFunction);
// 使用LongBinaryOperator对当前值和第一个参数进行计算,并更新当前值.
public final long accumulateAndGet(T obj, long x, LongBinaryOperator accumulatorFunction);

  AtomicLong、AtomicLongArray、AtomicLongFieldUpdater使用方式与AtomicInteger、AtomicIntegerArray、AtomicIntegerFieldUpdater基本保持一致,只要搞清楚其中一种类的操作方式,另一个也可以一样使用。

  注:文中源码均来自于JDK1.8版本,不同版本间可能存在差异。

  如果有哪里有不明白或不清楚的内容,欢迎留言哦!

这篇关于AtomicLong、AtomicLongArray、AtomicLongFieldUpdater 深入源码解析的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


原文地址:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.chinasem.cn/article/393597

相关文章

MySQL CTE (Common Table Expressions)示例全解析

《MySQLCTE(CommonTableExpressions)示例全解析》MySQL8.0引入CTE,支持递归查询,可创建临时命名结果集,提升复杂查询的可读性与维护性,适用于层次结构数据处... 目录基本语法CTE 主要特点非递归 CTE简单 CTE 示例多 CTE 示例递归 CTE基本递归 CTE 结

Spring Boot 3.x 中 WebClient 示例详解析

《SpringBoot3.x中WebClient示例详解析》SpringBoot3.x中WebClient是响应式HTTP客户端,替代RestTemplate,支持异步非阻塞请求,涵盖GET... 目录Spring Boot 3.x 中 WebClient 全面详解及示例1. WebClient 简介2.

在MySQL中实现冷热数据分离的方法及使用场景底层原理解析

《在MySQL中实现冷热数据分离的方法及使用场景底层原理解析》MySQL冷热数据分离通过分表/分区策略、数据归档和索引优化,将频繁访问的热数据与冷数据分开存储,提升查询效率并降低存储成本,适用于高并发... 目录实现冷热数据分离1. 分表策略2. 使用分区表3. 数据归档与迁移在mysql中实现冷热数据分

C#解析JSON数据全攻略指南

《C#解析JSON数据全攻略指南》这篇文章主要为大家详细介绍了使用C#解析JSON数据全攻略指南,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录一、为什么jsON是C#开发必修课?二、四步搞定网络JSON数据1. 获取数据 - HttpClient最佳实践2. 动态解析 - 快速

Spring Boot3.0新特性全面解析与应用实战

《SpringBoot3.0新特性全面解析与应用实战》SpringBoot3.0作为Spring生态系统的一个重要里程碑,带来了众多令人兴奋的新特性和改进,本文将深入解析SpringBoot3.0的... 目录核心变化概览Java版本要求提升迁移至Jakarta EE重要新特性详解1. Native Ima

spring中的@MapperScan注解属性解析

《spring中的@MapperScan注解属性解析》@MapperScan是Spring集成MyBatis时自动扫描Mapper接口的注解,简化配置并支持多数据源,通过属性控制扫描路径和过滤条件,利... 目录一、核心功能与作用二、注解属性解析三、底层实现原理四、使用场景与最佳实践五、注意事项与常见问题六

nginx -t、nginx -s stop 和 nginx -s reload 命令的详细解析(结合应用场景)

《nginx-t、nginx-sstop和nginx-sreload命令的详细解析(结合应用场景)》本文解析Nginx的-t、-sstop、-sreload命令,分别用于配置语法检... 以下是关于 nginx -t、nginx -s stop 和 nginx -s reload 命令的详细解析,结合实际应

MyBatis中$与#的区别解析

《MyBatis中$与#的区别解析》文章浏览阅读314次,点赞4次,收藏6次。MyBatis使用#{}作为参数占位符时,会创建预处理语句(PreparedStatement),并将参数值作为预处理语句... 目录一、介绍二、sql注入风险实例一、介绍#(井号):MyBATis使用#{}作为参数占位符时,会

深入理解Go语言中二维切片的使用

《深入理解Go语言中二维切片的使用》本文深入讲解了Go语言中二维切片的概念与应用,用于表示矩阵、表格等二维数据结构,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来一起学习学习吧... 目录引言二维切片的基本概念定义创建二维切片二维切片的操作访问元素修改元素遍历二维切片二维切片的动态调整追加行动态

PostgreSQL的扩展dict_int应用案例解析

《PostgreSQL的扩展dict_int应用案例解析》dict_int扩展为PostgreSQL提供了专业的整数文本处理能力,特别适合需要精确处理数字内容的搜索场景,本文给大家介绍PostgreS... 目录PostgreSQL的扩展dict_int一、扩展概述二、核心功能三、安装与启用四、字典配置方法