AtomicInteger源码

news2024/11/24 1:01:59

介绍

Atomic包是java.util.concurrent下的另一个专门为线程安全设计的Java包,包含多个原子操作类。这个包里面提供了一组原子变量类。其基本的特性就是在多线程环境下,当有多个线程同时执行这些类的实例包含的方法时,具有排他性,即当某个线程进入方法,执行其中的指令时,不会被其他线程打断,而别的线程就像自旋锁一样,一直等到该方法执行完成,才由JVM从等待队列中选择一个另一个线程进入,这只是一种逻辑上的理解。实际上是借助硬件的相关指令来实现的,不会阻塞线程(或者说只是在硬件级别上阻塞了)。可以对基本数据、数组中的基本数据、对类中的基本数据进行操作。原子变量类相当于一种泛化的volatile变量,能够支持原子的和有条件的读-改-写操作。

AtomicInteger是java.util.concurrent.atomic包下的一个提供原子操作的Integer的类。在多线程环境中,++i和i++、–i和i–操作并不是线程安全的,在使用的时候,不可避免的会用到synchronized关键字,而AtomicInteger则通过一种线程安全的加减操作接口保证在多线程环境下对整型变量的原子性操作。。

public class AtomicInteger extends Number implements java.io.Serializable 

image-20230625184011584

常量&变量

    //序列化版本号
    private static final long serialVersionUID = 6214790243416807050L;

    // setup to use Unsafe.compareAndSwapInt for updates
    //unsafe常量,设置为使用Unsafe.compareAndSwapInt进行更新
    private static final Unsafe unsafe = Unsafe.getUnsafe();
    //AtomicInteger的值在内存地址的偏移量,用它进行CAS操作
    private static final long valueOffset;

    //objectFieldOffset是一个本地方法,返回属性相对于对象的偏移量,这里使用反射获取属性。
    static {
        try {
            valueOffset = unsafe.objectFieldOffset
                (AtomicInteger.class.getDeclaredField("value"));
        } catch (Exception ex) { throw new Error(ex); }
    }

    //AtomicInteger当前的值
    private volatile int value;

Unsafe 是 CAS 的核心类,Java 无法直接访问底层操作系统,而是通过本地(native)方法来访问。不过尽管如此,JVM 还是开了一个后门:Unsafe 类,它提供了硬件级别的原子操作。

Unsafe类是java中未被公开的一个类,可以使用反射来调用其方法

构造方法

    /**
     * Creates a new AtomicInteger with the given initial value.
     *
     * @param initialValue the initial value
     */
    public AtomicInteger(int initialValue) {
        value = initialValue;
    }

    /**
     * Creates a new AtomicInteger with initial value {@code 0}.
     */
    public AtomicInteger() {
    }

常用方法

get()

获取当前值

    /**
     * Gets the current value.
     *
     * @return the current value
     * 直接返回变量value
     */
    public final int get() {
        return value;
    }

set(int newValue)

newValue表示要设置的新值。该方法会以原子方式将当前值设置为指定的值。

    /**
     * Sets to the given value.
     *
     * @param newValue the new value
     *  通过参数newValue将变量value进行值的更新
     */
    public final void set(int newValue) {
        value = newValue;
    }

lazySet(int newValue)

azySet方法是使用volatile关键字确保可见性的一种写方法,它是一种非阻塞的方法,可以减少线程间的竞争。

    /**
     * Eventually sets to the given value.
     *
     * @param newValue the new value
     * @since 1.6
     * 通过unsafe变量最终设置为给定的值。
     */
    public final void lazySet(int newValue) {
        unsafe.putOrderedInt(this, valueOffset, newValue);
    }

方法内部使用了一个putOrderedInt方法,该方法的作用是在不需要锁定功能的前提下,将值设置到指定偏移量的int型字段中,并使用volatile语义保证该操作的可见性。

相比于set方法,lazySet方法的优势在于不需要等待写入操作完成,所以它的性能更好。但是它也存在一个缺点,即它不能保证读操作的可见性,因为它没有使用锁,因此可能出现缓存一致性问题。

getAndSet(int newValue)

获取当前值,并设置新值,这个操作是原子性的,即在多线程环境下,任何时刻只有一个线程能够执行这个操作。

    /**
     * Atomically sets to the given value and returns the old value.
     *
     * @param newValue the new value
     * @return the previous value
     * 先获取旧值再更新新值,还是利用unsafe的内部方法来进行操作
     */
    public final int getAndSet(int newValue) {
        return unsafe.getAndSetInt(this, valueOffset, newValue);
    }

compareAndSet(int expect, int update)

比较当前AtomicInteger对象的值和一个期望值,如果相等,就将AtomicInteger对象的值修改为一个新值。同时,这个操作是原子性的,保证在多线程的情况下,只有一个线程能够成功修改AtomicInteger对象的值。

    /**
     * Atomically sets the value to the given updated value
     * if the current value {@code ==} the expected value.
     *
     * @param expect the expected value
     * @param update the new value
     * @return {@code true} if successful. False return indicates that
     * the actual value was not equal to the expected value.
     * CAS方法,利用判断旧值符合预期值并且更新新的值
     */
    public final boolean compareAndSet(int expect, int update) {
        return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
    }

weakCompareAndSet

AtomicInteger的weakCompareAndSet方法是一种无锁的原子操作,用于比较并设置操作。该方法比较当前AtomicInteger的值与给定的预期值,如果相等,则将AtomicInteger的值设为新值,并返回true;否则不作任何操作,返回false。与compareAndSet方法相比,weakCompareAndSet方法不保证在高并发环境下的操作的原子性,但可以提高系统的并发性能。

    /**
     * Atomically sets the value to the given updated value
     * if the current value {@code ==} the expected value.
     *
     * <p><a href="package-summary.html#weakCompareAndSet">May fail
     * spuriously and does not provide ordering guarantees</a>, so is
     * only rarely an appropriate alternative to {@code compareAndSet}.
     *
     * @param expect the expected value
     * @param update the new value
     * @return {@code true} if successful
     */
    public final boolean weakCompareAndSet(int expect, int update) {
        return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
    }

其中,unsafe.compareAndSwapInt是Java中的一个本地方法,可以直接操作内存,实现无锁并发控制。在该方法中,参数this表示当前对象,valueOffset表示该对象内存地址中值的偏移量(由于AtomicInteger是基于内存地址进行操作的,因此需要根据偏移量来访问对象中的值),expect表示预期值,update表示更新值。如果偏移量处的值与expect相等,则将值更新为update,并返回true,否则不作任何操作,返回false。

getAndIncrement()

获取当前值,并递增1

    /**
     * Atomically increments by one the current value.
     *
     * @return the previous value
     * 先获取旧值然后再旧值上加一,利用的unsafe内部方法
     */
    public final int getAndIncrement() {
        return unsafe.getAndAddInt(this, valueOffset, 1);
    }

getAndDecrement

获取当前值,并递减1

    /**
     * Atomically decrements by one the current value.
     *
     * @return the previous value
     * 将当前值自动减1
     */
    public final int getAndDecrement() {
        return unsafe.getAndAddInt(this, valueOffset, -1);
    }

getAndAdd(int delta)

获取当前值,并加上delta的值

    /**
     * Atomically adds the given value to the current value.
     *
     * @param delta the value to add
     * @return the previous value
     * 先获取旧值然后再旧值上加上指定值,利用的unsafe内部方法
     */
    public final int getAndAdd(int delta) {
        return unsafe.getAndAddInt(this, valueOffset, delta);
    }
    public final int addAndGet(int delta) {
        return unsafe.getAndAddInt(this, valueOffset, delta) + delta;
    }

addAndGet

用于对AtomicInteger对象的值进行原子性的加操作,并返回加操作后的值。

    /**
     * Atomically adds the given value to the current value.
     *
     * @param delta the value to add
     * @return the updated value
     */
    public final int addAndGet(int delta) {
        return unsafe.getAndAddInt(this, valueOffset, delta) + delta;
    }

incrementAndGet

递增1

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

decrementAndGet

递减1

    /**
     * Atomically decrements by one the current value.
     *
     * @return the updated value
     */
    public final int decrementAndGet() {
        return unsafe.getAndAddInt(this, valueOffset, -1) - 1;
    }

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

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

相关文章

大坝渗流监测的目的和意义

​  大坝渗流监测是对坝体内渗流场进行的监测&#xff0c;是确保大坝安全运行的重要手段。通过监测&#xff0c;可以掌握渗流场的变化规律&#xff0c;并根据渗流场的变化趋势预测坝体、坝基可能出现的问题。通常根据渗漏量与渗流量两个指标来进行监测&#xff0c;即渗漏量小…

【ndarry的基本操作】——numpy03

目录索引 基本索引和切片&#xff1a;普通索引&#xff1a;省略索引&#xff1a;多省略索引&#xff1a;间隔索引&#xff1a; 形态变换操作&#xff1a;reshape()&#xff1a;resize()&#xff1a;transpose()&#xff1a;*通过参数进行转置&#xff1a;* flatten()&#xff1…

usb转8路串口模块

开源USB转8路串口PCB设计 文章目录 开源USB转8路串口PCB设计1. 简介2. 说明3. 一种跨电脑跨USB口的端口号自动识别方法4.开源地址 今天给大家介绍一款USB转8路串口的PCB设计&#xff0c;并提供一种跨电脑跨USB口的端口号自动识别方法。 1. 简介 芯片采用沁恒的CH348Q&#xff…

Kotlin Jetpack Compose - 实现Tab布局

Tab布局是一种常见的UI设计&#xff0c;它允许用户在不同的视图或数据集之间切换。我们将使用Jetpack Compose的 TabRow 和 ScrollableTabRow 组件来实现这个布局。 一、基本的Tab布局——TabRow 二、滚动的Tab布局——ScrollableTabRow 组件 三、自定义Tab组件 一、基本的T…

音视频数据处理-H265/HEVC视频码流分析

一、H265概述 H265/HEVC&#xff08;Hight Efficiency Video Coding&#xff09;是由ITU-T和ISO/IEC两大组织在H264/AVC的基础之上推出的新一代高效视频编码标准&#xff0c;主要为应对高清和超高清视频在网络传输和数据存储方面带来的挑战。上一篇文章对H264/AVC视频码流进行…

chatgpt赋能python:Python自动化定位元素的方法详解

Python自动化定位元素的方法详解 作为一名Python编程经验丰富的工程师&#xff0c;我经常需要用到自动化定位元素的方法。今天&#xff0c;我想与大家分享一下在Python中如何自动化定位元素&#xff0c;以帮助那些想要进行Web自动化测试的开发者们。 什么是自动化定位元素 在…

chatgpt赋能python:Python聊天界面:开发高效且易于使用的消息应用

Python聊天界面&#xff1a;开发高效且易于使用的消息应用 Python是一种十分流行的编程语言&#xff0c;最近几年来&#xff0c;这种语言在GUI应用程序开发方面也越来越受欢迎。在本篇文章中&#xff0c;我们将介绍如何使用Python开发一个高效且易于使用的消息应用程序——聊天…

chatgpt赋能python:Python自动化定位——解放SEO员工的双手

Python自动化定位——解放SEO员工的双手 SEO&#xff08;Search Engine Optimization&#xff09;是现代数字营销中必不可少的一环。面对庞大的网络世界&#xff0c;SEO员工们日复一日地进行着关键词排名、页面跳转、链接检测等重复且繁琐的工作。而Python作为一种功能强大、易…

chatgpt赋能python:Python自动执行:提高效率,增强灵活性

Python自动执行&#xff1a; 提高效率&#xff0c;增强灵活性 随着时代进步&#xff0c;人们日常生活中越来越依赖计算机和网络技术&#xff0c;而在编程领域&#xff0c;Python语言作为一种高效、可读性好、易学易用的语言&#xff0c;得到了广泛应用。其中&#xff0c;Pytho…

【算法之栈与队列I】leetcode239. 滑动窗口最大值

232.用栈实现队列 力扣题目链接 请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作&#xff08;push、pop、peek、empty&#xff09;&#xff1a; 实现 MyQueue 类&#xff1a; void push(int x) 将元素 x 推到队列的末尾int pop() 从队列的开头移除并…

使用netwox 的实例进行ARP地址解析协议分析【网络工程】(保姆级图文)

目录 1. netwox 构造 ARP 报文使用 netwox 工具构造 ARP 包。1) 查看 netwox 所在主机默认的 ARP 包的相关信息&#xff0c;执行命令如下&#xff1a;2) 构造 ARP 请求包&#xff0c;请求目标主机 192.168.43.95&#xff0c;执行命令如下&#xff1a;3) 为了验证构造的 ARP 请求…

IDEA(2021.3.3) 登录Github copilot最新版本报错解决

"Request sign ln Initiate failed with message:read ECONNRESET, request id: 6, error code:-32603 " .在获得github认证后的登录设备验证阶段弹出。此处应该为login 弹出异常&#xff0c;方法一&#xff1a;先使用Github 520进行动态替换&#xff0c;打开自己hos…

霍夫变换椭圆检测(matlab仿真与图像处理系列第2期)

概述 椭圆检测是图像处理中的一个重要问题,其目的是从图像中检测出可能存在的椭圆。在实际的应用中,椭圆常常被用来描述物体的形状或者得到物体的尺寸信息。 传统的椭圆检测方法通常采用二维Hough变换,在求解过程中需要处理大量的数据,并且计算复杂度高,导致速度较慢,…

linux系统grep文本三剑客之一

文章目录 一、grep常用选项二、正则表达式三、sort命令四、tr命令五、cut命令六、split命令七、paste命令八、正则表达式总结 一、grep常用选项 grep&#xff1a;文本三剑客之一&#xff0c;对文本内容进行过滤&#xff0c;支持正则表达式&#xff0c;针对行来进行处理。 -m&a…

【C++】 Qt-信号与槽

文章目录 基本概念添加信号与槽方法一方法二 自定义信号与槽CheckBox自定义QMessageBox自定义信号 信号与槽多对多一个信号连接多个槽多个信号连接一个槽一个信号连接一个信号连接一个槽 断开连接方法一方法二判断是否连接成功 基本概念 信号&#xff08;signal&#xff09;和…

chatgpt赋能python:Python自动执行函数——提高生产力的利器

Python自动执行函数 —— 提高生产力的利器 Python作为一种高级编程语言&#xff0c;具有强大的自动化能力&#xff0c;可以轻松实现多种任务的自动执行&#xff0c;从而提高生产力和效率。这篇文章将介绍如何使用Python自动执行函数&#xff0c;以及它对于SEO的重要意义。 什…

Flutter Dart类

目录 类 构造函数 命名构造函数 重定向构造函数 常量构造函数 工厂构造函数 Getters 和 Setters 初始化列表 可覆写的操作符 类 创建一个dart文件&#xff0c;名称全小写&#xff0c;里面的类可以按照驼峰命名法。文件名和类名可以不保持统一&#xff0c;这个跟Java有明…

Scrapy: 一个强大的 Python 爬虫框架--介绍--下载--启动!!

目录 Scrapy 影响力 介绍 主要特点 架构 运行流程 基本使用 安装 创建 Scrapy 项目 创建爬虫 爬虫包含的内容 运行爬虫 Scrapy 影响力 作为目前爬虫主流框架之一&#xff0c;Scrapy的影响力和应用范围非常广泛&#xff1a; 根据GitHub上的数据&#xff0c;Scrapy是一…

ERR! code ERR_SOCKET_TIMEOUT

问题 安装npm包&#xff0c;终端报错ERR! code ERR_SOCKET_TIMEOUT ERR! code ERR_SOCKET_TIMEOUT详细问题 笔者运行以下命令重新安装依赖项&#xff1a; npm install控制台报错&#xff0c;具体报错信息如下 npm ERR! code ERR_SOCKET_TIMEOUT npm ERR! network Socket t…

【C++】【VLD】VLD检测内存泄漏

【C】【VLD】VLD检测内存泄漏 C/C 程序越复杂&#xff0c;内存的管理显得越重要&#xff0c;稍有不慎就会出现泄漏。如果内存泄漏不是很严重&#xff0c;在短时间内对程序不会有太大影响&#xff0c;这也使得内存泄漏问题有很强的隐蔽性&#xff0c;不易被发现。 然而不管内存…