JDK源码——Atomic包(一)

news2024/9/23 7:21:30

包介绍

JDK的atomic包提供了一组原子类,用于多线程环境中的原子操作,确保线程安全和高性能

Atomic包是Java在并发编程中的重要工具,它利用CAS(Compare-And-Swap)机制保证操作的原子性,同时避免了重量级锁的使用,提高了并发性能。Atomic包中的类通过底层处理器提供的原子指令实现,但不同的CPU架构可能提供的原子指令不同,有时可能需要某种形式的内部锁,因此不能绝对保证线程不被阻塞。
在这里插入图片描述

基本类型

AtomicInteger

提供了一种线程安全的方式来操作整数。
在这里插入图片描述
主要提供了以下方法:
在这里插入图片描述

  1. getAndIncrement(): 获取当前值并自增,返回旧值。
  2. get(): 获取当前值。
  3. compareAndSet(int expect, int update): 如果当前值等于预期值(expect),则将其更新为新的值(update)。如果更新成功,返回 true;否则返回 false。
  4. getAndSet(int newValue): 获取当前值并设置为指定的新值,返回旧值。
  5. floatValue(): 将当前值转换为 float 类型。
  6. getAndAdd(int delta): 获取当前值并加上指定的增量(delta),返回旧值。
  7. getAndUpdate(IntUnaryOperator updateFunction): 获取当前值并应用给定的一元操作函数(updateFunction),返回旧值。
  8. intValue(): 将当前值转换为 int 类型。
  9. getAndAccumulate(int x, IntBinaryOperator accumulatorFunction): 获取当前值并与给定的值(x)应用二元操作函数(accumulatorFunction),返回旧值。
  10. toString(): 返回当前值的字符串表示形式。
  11. lazySet(int newValue): 设置当前值为指定的新值,但不保证立即可见性,可能会延迟到下一次访问。
  12. incrementAndGet(): 自增并返回新值。
  13. accumulateAndGet(int x, IntBinaryOperator accumulatorFunction): 与给定的值(x)应用二元操作函数(accumulatorFunction)并返回结果。
  14. decrementAndGet(): 自减并返回新值。
  15. longValue(): 将当前值转换为 long 类型。
  16. addAndGet(int delta): 增加指定的增量(delta)并返回新值。
  17. doubleValue(): 将当前值转换为 double 类型。
  18. weakCompareAndSet(int expect, int update): 类似于 compareAndSet,但如果当前值不等于预期值,它可能不会立即失败,而是尝试再次进行比较和设置。这在某些情况下可以提高性能,但可能导致不一致的结果。
  19. updateAndGet(IntUnaryOperator updateFunction): 应用给定的一元操作函数(updateFunction)并返回结果。
  20. set(int newValue): 设置当前值为指定的新值。

原理

  1. 原子性操作:AtomicInteger使用CAS(比较替换)算法来实现其内部的值的原子性更新。CAS算法是硬件级别的原子操作,它可以在没有锁的情况下进行线程安全的更新。

  2. Unsafe类:AtomicInteger的内部实现使用了Unsafe类的native方法,如compareAndSwapInt,这是一个底层的、高效的原子操作方法,它直接与操作系统和硬件交互,实现了原子性的保证。

/**
通过调用Unsafe.getUnsafe()方法获取Unsafe实例。Unsafe类提供了一些底层操作,可以直接访问对象和内存,绕过了Java的安全检查机制。

定义了一个静态常量valueOffset,用于存储字段"value"在内存中的偏移量。

在静态初始化块中,使用unsafe.objectFieldOffset方法获取字段"value"的偏移量。这个方法需要一个Field对象作为参数,因此需要先通过反射获取AtomicInteger类的"value"字段。

如果获取偏移量的过程中发生异常(例如找不到字段),则抛出一个Error。

**/
  private static final Unsafe unsafe = Unsafe.getUnsafe();
    private static final long valueOffset;

    static {
        try {
            valueOffset = unsafe.objectFieldOffset
                (AtomicInteger.class.getDeclaredField("value"));
        } catch (Exception ex) { throw new Error(ex); }
    }
  1. 字段更新:AtomicInteger使用volatile关键字声明其内部值字段,确保字段的可见性和有序性,防止指令重排序导致的问题。
 private volatile int value;
  1. 方法实现:AtomicInteger提供了一系列的方法,如getAndIncrementcompareAndSet等,这些方法都是利用CAS算法来实现的,它们可以在没有锁的情况下,保证操作的原子性。
public final int getAndIncrement() {
        return unsafe.getAndAddInt(this, valueOffset, 1);
    }

 public final boolean compareAndSet(int expect, int update) {
        return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
    }
  1. 性能优势:由于AtomicInteger不需要使用锁,它通常比使用synchronized关键字或者显式锁(如ReentrantLock)的性能要好,尤其是在高并发的情况下。

  2. 内存开销:AtomicInteger相对于普通的Integer会有稍微大一点的内存开销,因为它需要额外的内存来存储一些操作所需的元数据。

  3. 限制:尽管AtomicInteger提供了原子性的保证,但是它不能保证操作的“逻辑原子性”。例如,如果你需要检查值,然后基于这个值进行更新(比如计数器小于10就增加),这样的操作序列就不能保证原子性,因为这个过程涉及到多个步骤,而CAS只能保证单个操作的原子性。

  4. 可扩展性:AtomicInteger是可扩展的,意味着你可以用它作为更复杂原子操作的基础,通过组合和扩展AtomicInteger的功能,可以构建更复杂的原子操作。

  5. 线程兼容性:AtomicInteger的操作是线程兼容的,这意味着在多线程环境中,你可以安全地使用AtomicInteger而不用担心线程安全问题。

  6. 使用场景:AtomicInteger适用于那些需要线程安全的整数操作,但不需要使用锁或者不希望有锁带来的性能开销的场景。

AtomicBoolean

类提供了一种线程安全的方式来操作布尔值。
在这里插入图片描述

主要提供了以下方法:
在这里插入图片描述

  1. getAndSet(boolean newValue): 将当前值设置为指定的新值,并返回旧值。这是一个原子操作,确保在多线程环境下的一致性。

  2. set(boolean newValue): 将当前值设置为指定的新值。这也是一个原子操作。

  3. get(): 获取当前的布尔值。这个方法是非原子的,但在多线程环境中使用时,由于其他原子操作的存在,可以保证读取到的值是一致的。

  4. compareAndSet(boolean expect, boolean update): 如果当前值等于预期值(expect),则将其更新为新的值(update)。如果更新成功,返回 true;否则返回 false。这是一个典型的CAS(Compare-and-Swap)操作,通常用于无锁编程。

  5. lazySet(boolean newValue): 将当前值设置为指定的新值,但可能会延迟该操作直到下一次访问。这是一种优化手段,可以减少不必要的内存屏障开销。

  6. weakCompareAndSet(boolean expect, boolean update): 类似于 compareAndSet,但如果当前值不等于预期值,它可能不会立即失败,而是尝试再次进行比较和设置。这在某些情况下可以提高性能,但可能导致不一致的结果。

  7. toString(): 返回当前布尔值的字符串表示形式。这个方法是非原子的,但在多线程环境中使用时,由于其他原子操作的存在,可以保证读取到的值是一致的。

AtomicLong

类提供了一种线程安全的方式来操作长整数。
在这里插入图片描述

主要提供了以下方法:
在这里插入图片描述

  1. VMSupportsCS8(): 返回一个布尔值,表示虚拟机是否支持CS8(Compare and Swap)操作。
  2. longValue(): 获取当前值作为长整型(long)。
  3. intValue(): 获取当前值作为整型(int)。
  4. toString(): 返回当前值的字符串表示形式。
  5. incrementAndGet(): 自增并返回新值。
  6. getAndAccumulate(long x, LongBinaryOperator accumulatorFunction): 获取当前值并与给定的值(x)应用二元操作函数(accumulatorFunction),返回旧值。
  7. getAndSet(long newValue): 获取当前值并设置为指定的新值,返回旧值。
  8. doubleValue(): 将当前值转换为双精度浮点数(double)。
  9. set(long newValue): 设置当前值为指定的新值。
  10. weakCompareAndSet(long expect, long update): 如果当前值等于预期值(expect),则将其更新为新的值(update)。如果更新成功,返回 true;否则返回 false。
  11. getAndUpdate(LongUnaryOperator updateFunction): 获取当前值并应用给定的一元操作函数(updateFunction),返回旧值。
  12. getAndIncrement(): 获取当前值并自增,返回旧值。
  13. accumulateAndGet(long x, LongBinaryOperator accumulatorFunction): 与给定的值(x)应用二元操作函数(accumulatorFunction)并返回结果。
  14. getAndAdd(long delta): 获取当前值并加上指定的增量(delta),返回旧值。
  15. get(): 获取当前值。
  16. lazySet(long newValue): 设置当前值为指定的新值,但不保证立即可见性,可能会延迟到下一次访问。
  17. compareAndSet(long expect, long update): 如果当前值等于预期值(expect),则将其更新为新的值(update)。如果更新成功,返回 true;否则返回 false。
  18. updateAndGet(LongUnaryOperator updateFunction): 应用给定的一元操作函数(updateFunction)并返回结果。
  19. floatValue(): 将当前值转换为单精度浮点数(float)。
  20. addAndGet(long delta): 增加指定的增量(delta)并返回新值。
  21. getAndDecrement(): 获取当前值并自减,返回旧值。
  22. decrementAndGet(): 自减并返回新值。

数组操作

AtomicIntegerArray

与AtomicLongArray类似,但是它用于操作int类型的数组。它也提供了一系列的原子操作方法,如get、set、compareAndSet等,以确保在多线程环境下对数组元素的操作是原子性的。
在这里插入图片描述
提供的以下方法:
在这里插入图片描述

  1. getAndIncrement(int): 获取指定索引位置的当前值,并将其自增1。返回自增前的值。
  2. accumulateAndGet(int, int, IntBinaryOperator): 对指定索引位置的元素进行累加操作,并返回累加后的结果。累加操作由提供的IntBinaryOperator参数定义。
  3. getAndDecrement(int): 获取指定索引位置的当前值,并将其自减1。返回自减前的值。
  4. getAndAccumulate(int, int, IntBinaryOperator): 对指定索引位置的元素进行累加操作,并返回累加后的结果。累加操作由提供的IntBinaryOperator参数定义。
  5. compareAndSet(int, int, int): 如果指定索引位置的当前值等于预期值(第二个参数),则将其更新为新值(第三个参数)。返回一个布尔值表示是否成功更新。
  6. compareAndSetRaw(long, int, int): 类似于compareAndSet,但使用长整型索引。
  7. addAndGet(int, int): 将指定的增量(第二个参数)添加到指定索引位置的元素上,并返回结果。
  8. checkedByteOffset(int): 检查给定的偏移量是否有效,并返回相应的字节偏移量。
  9. getAndSet(int, int): 获取指定索引位置的当前值,并将其设置为新值(第二个参数)。返回旧值。
  10. byteOffset(int): 返回指定索引位置的字节偏移量。
  11. length(): 返回数组的长度。
  12. get(int): 获取指定索引位置的值。
  13. lazySet(int, int): 设置指定索引位置的值,但不保证立即可见性。
  14. decrementAndGet(int): 获取指定索引位置的当前值,并将其自减1。返回自减前的值。
  15. weakCompareAndSet(int, int, int): 如果指定索引位置的当前值等于预期值(第二个参数),则尝试将其更新为新值(第三个参数)。返回一个布尔值表示是否成功更新。
  16. toString(): 返回数组的字符串表示形式。
  17. set(int, int): 设置指定索引位置的值。
  18. getRaw(long): 获取指定索引位置的值,使用长整型索引。
  19. getAndUpdate(int, IntUnaryOperator): 获取指定索引位置的当前值,并应用给定的一元操作函数(第二个参数)。返回操作后的结果。
  20. incrementAndGet(int): 获取指定索引位置的当前值,并将其自增1。返回自增后的值。
  21. getAndAdd(int, int): 获取指定索引位置的当前值,并将其加上指定的增量(第二个参数)。返回结果。
  22. updateAndGet(int, IntUnaryOperator): 应用给定的一元操作函数(第二个参数)到指定索引位置的元素上,并返回操作后的结果。

AtomicLongArray

提供了一种线程安全的方式来操作long类型的数组。它提供了一系列的原子操作方法,如get、set、compareAndSet等,这些方法可以确保在多线程环境下对数组元素的操作是原子性的。
在这里插入图片描述
类方法说明:

  1. set(int index, long newValue): 将指定索引位置的元素设置为新值。
  2. addAndGet(int index, long delta): 将指定的增量(delta)添加到指定索引位置的元素上,并返回结果。
  3. getAndUpdate(int index, LongUnaryOperator updateFunction): 获取指定索引位置的当前值,应用给定的一元操作函数(updateFunction),并将结果写回该位置,最后返回操作前的值。
  4. getAndDecrement(int index): 获取指定索引位置的当前值,将其自减1,并将结果写回该位置,最后返回操作前的值。
  5. checkedByteOffset(int index): 检查给定的索引是否有效,并返回相应的字节偏移量。
  6. getRaw(long offset): 获取指定偏移量处的元素值。
  7. lazySet(int index, long newValue): 设置指定索引位置的元素值为新值,但不保证立即可见性。
  8. length(): 返回数组的长度。
  9. compareAndSet(int index, long expect, long update): 如果指定索引位置的当前值等于预期值(expect),则将其更新为新值(update)。返回一个布尔值表示是否成功更新。
  10. accumulateAndGet(int index, long x, LongBinaryOperator accumulatorFunction): 对指定索引位置的元素进行累加操作,并返回累加后的结果。累加操作由提供的累加器函数(accumulatorFunction)定义。
  11. getAndIncrement(int index): 获取指定索引位置的当前值,并将其自增1,然后将结果写回该位置,最后返回操作前的值。
  12. getAndAccumulate(int index, long x, LongBinaryOperator accumulatorFunction): 对指定索引位置的元素进行累加操作,并返回累加后的结果。累加操作由提供的累加器函数(accumulatorFunction)定义。
  13. getAndAdd(int index, long delta): 获取指定索引位置的当前值,将其加上指定的增量(delta),然后将结果写回该位置,最后返回操作前的值。
  14. updateAndGet(int index, LongUnaryOperator updateFunction): 应用给定的一元操作函数(updateFunction)到指定索引位置的元素上,并返回操作后的结果。
  15. getAndSet(int index, long newValue): 获取指定索引位置的当前值,并将其设置为新值(newValue)。返回旧值。
  16. weakCompareAndSet(int index, long expect, long update): 如果指定索引位置的当前值等于预期值(expect),则尝试将其更新为新值(update)。返回一个布尔值表示是否成功更新。
  17. incrementAndGet(int index): 获取指定索引位置的当前值,将其自增1,然后将结果写回该位置,最后返回操作后的值。
  18. toString(): 返回数组的字符串表示形式。
  19. byteOffset(int index): 返回指定索引位置的字节偏移量。
  20. decrementAndGet(int index): 获取指定索引位置的当前值,将其自减1,然后将结果写回该位置,最后返回操作后的值。
  21. get(int index): 获取指定索引位置的值。
  22. compareAndSetRaw(long offset, long expect, long update): 如果指定偏移量处的当前值等于预期值(expect),则将其更新为新值(update)。返回一个布尔值表示是否成功更新。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

3.Redis数据类型(二)

LIST List 是一个简单的双向链表,支持从两端进行插入和删除操作。 常用命令: lpush/rpush/lrange lpush 插入一个或多个元素到列表的左端。 rpush 插入一个或多个元素到列表的右端。 lrange key start stop 获取元素(前闭后闭&#xff0…

构建可刷卡手持终端,思路与必备元素剖析-SAAS 本地化及未来之窗行业应用跨平台架构

构建可刷卡手持终端,思路与必备元素剖析 一、终端开发必要性 1.终端携带方便,适合空间小,外出 2.可供电,外带设备比较方便 3.大多数终端可以不需要网络独立使用,适合特殊场景 二、终端软件爱基本功能 1.便捷的终端…

Java重修笔记 第三十天 异常

异常的分类 1. Error(错误):Java虚拟机无法解决的致命问题,例如StackOverflowError[栈溢出] 2. Exception(异常):其它因编程错误或偶然的外在因素导致的一般性问题,可以使用针对性…

【iOS多线程(四)】线程安全+13种锁

线程安全13种锁 线程安全1. 为什么要线程安全出现线程安全的原理解决方法 2. 自旋锁和互斥锁自旋锁(Spin lock)互斥锁两种锁的加锁原理对比两种锁的应用 3. 13种锁1. OSSpinLock (已弃用)2. os_unfair_lock3.pthread_mutex 4. NSLock5. NSRecursiveLock6. NSConditi…

C++ IOStream

IOStream 类流特性 不可赋值和复制缓冲重载了<< >> 状态位 示例 状态位操作函数coutcin getget(s,n)/get(s,n,d):getline otherif(!fs)/while(cin) operator void*()与 operator!()代码示例 File Stream open 函数 文件打开方式 文件读写 读写接口 一次读一个字符…

SpringBoot学习之EasyExcel解析合并单元格(三十九)

本解析主要采用反射来修改EasyExcel 返回的默认数据结构实现。 一、待解析表格 二、依赖 全部pom.xml文件如下,仅作参考: <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLo…

LLM - 使用 HuggingFace + Ollama 部署最新大模型 (GGUF 格式 与 Llama 3.1)

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://spike.blog.csdn.net/article/details/141028040 免责声明&#xff1a;本文来源于个人知识与公开资料&#xff0c;仅用于学术交流&#xff0c;欢迎讨论&#xff0c;不支持转载。 Ollama…

创建一个自己的列表窗口

文章目录 背景&#xff1a;在QT的设计中&#xff0c;对于控件库提供的控件满足不了项目的需求&#xff0c;就像自定义一些控件&#xff0c;本文是自定义一个列表窗口。效果展示 一、创建基本的QT模板&#xff1a;1.创建mainwindow2.创建VerticalTextDelegate 二&#xff1a; 插…

零拷贝的发展历程

零拷贝 零拷贝是指计算机执行 IO 操作时&#xff0c;CPU 不需要将数据从一个存储区域复制到另一个存储区域&#xff0c;从而可以减少上下文切换以及 CPU的拷贝时间。它是一种I/O 操作优化技术。 传统IO的执行流程&#xff1a;传统的 IO 流程&#xff0c;包括 read 读 和 write…

2024.8.08(python)

一、搭建python环境 1、检查是否安装python [rootpython ~]# yum list installed | grep python [rootpython ~]# yum list | grep python3 2、安装python3 [rootpython ~]# yum -y install python3 安装3.12可以使用源码安装 3、查看版本信息 [rootpython ~]# python3 --vers…

C++(类和对象.下)

类型转换 先给出以下代码&#xff1a; #define _CRT_SECURE_NO_WARNINGS 1 #include<iostream> using namespace std; class B { private:int _a1; public:B(int a){_a1 a;}void Print() {cout << _a1<< endl;} }; int main() {//实例化对象1B b(1);b.Pri…

video-retalking部署安装,在服务器Ubuntu22.04系统下

video-retalking部署安装&#xff0c;在服务器Ubuntu22.04系统下 一、ubuntu基本环境配置1.更新包列表&#xff1a;2. 安装英伟达显卡驱动2.1 使用wget在命令行下载驱动包2.2 更新软件列表和安装必要软件、依赖2.2 卸载原有驱动2.3 安装驱动2.4 安装CUDA2.5 环境变量配置 二、安…

基于YOLOv10深度学习的交通信号灯检测识别系统【python源码+Pyqt5界面+数据集+训练代码】红绿灯检测、目标检测、人工智能

《博主简介》 小伙伴们好&#xff0c;我是阿旭。专注于人工智能、AIGC、python、计算机视觉相关分享研究。 ✌更多学习资源&#xff0c;可关注公-仲-hao:【阿旭算法与机器学习】&#xff0c;共同学习交流~ &#x1f44d;感谢小伙伴们点赞、关注&#xff01; 《------往期经典推…

易语言窗口1以及其它子窗口在任务栏显示的方法以及源代码

大家都知道在启动子程序中载入窗口里&#xff0c;窗口就不在任务栏中显示了 用什么办法可以解决这个问题呢 本例程教源码教你如何解决

零拷贝:原理与实现

1. 简介 I/O 或输入/输出通常意味着中央处理器 (CPU) 与外部设备&#xff08;如磁盘、鼠标、键盘等&#xff09;之间的读写。在深入研究零拷贝之前&#xff0c;有必要指出磁盘 I/O&#xff08;包括磁盘设备和其他块导向设备&#xff09;和网络 I/O 之间的区别。 磁盘 I/O 的常…

Vue3简单介绍和快速体验

目录 前言 1. Vue3介绍 1.1 Vue的两个核心功能&#xff1a; 1.2 Vue作者介绍 2. Vue3快速体验(非工程化方式) 2.1 所有代码 2.2 导入js 2.3 一些基本指令 2.4 app对象的创建和挂载 ​ 前言 在学习Vue3之前,自己已经学习过的vue2了,在学习Vue3后还是能感觉到2和3在使用…

媒体资讯视频数据采集-yt-dlp-python实际使用-下载视频

对于视频二创等一些业务场景&#xff0c;可能要采集youtube等的相关媒体视频资源&#xff0c;使用[yt-dlp](https://github.com/yt-dlp/yt-dlp)是一个不错的选择&#xff0c;提供的命令比较丰富&#xff0c;场景比较全面yt-dlp 是一个用 Python 编写的命令行工具&#xff0c;主…

数据结构和算法|递归算法那些事(递归算法的时间复杂度和尾递归优化)

对于文章的第一部分&#xff0c;递归算法的时间复杂度&#xff0c;来自于代码随想录文章:通过一道面试题目&#xff0c;讲一讲递归算法的时间复杂度&#xff01; 对于第二节尾递归优化来自于B站&#xff1a;尾递归优化&#xff1a;你的递归调用是如何被优化的&#xff1f; 关于…

什么是占空比?什么是周期?什么是频率?

一、什么是占空比&#xff1f; 占空比(Duty Cycle)是脉冲信号中高电平持续时间与整个周期时间的比率。它通常用于描述脉冲宽度调制(PWM)信号&#xff0c;其中信号在一定频率下在高电平和低电平之间切换。 图1.1 60%占空比信号 占空比计算公式如下&#xff1a; 脉冲高电平持续时…

护眼首选,一线智联!AOC Q27E12C商用显示器,摆脱束缚高效办公!

摘要&#xff1a;QHD广色域护眼显示器&#xff0c;减负提效商务利器&#xff01; 不管是日常处理报表、制作方案还是进行文字创作、设计剪辑&#xff0c;都离不开商用显示器的身影。相较于传统显示器&#xff0c;商用显示器往往更有助于减负提效&#xff0c;提高企业生产力&am…