AtomicInteger

1. 前言

AtomicInteger是Java中的一个原子整数类,它提供了一种在多线程环境下进行原子性操作的方法。所谓原子性操作是指不会被线程调度机制打断的操作;这些操作可以在可能被其他线程影响的情况下作为一个不可分割的整体执行。

在并发编程中,如果多个线程同时对同一个变量进行读取和写入操作,会存在竞态条件(Race Condition),导致数据不一致或错误。为了解决这种问题,Java提供了一系列的原子类,其中包括AtomicInteger。

AtomicInteger可以保证对整型变量的操作是原子性的,比如增加、减少操作。它使用了底层的CAS(Compare and Swap)操作来实现原子性。

2. 介绍CAS

AtomicInteger的实现依赖于底层的CAS(Compare-And-Swap)操作,确保其操作是原子性的。CAS是一种硬件级别的原子操作,通常由处理器直接支持,它可以在多线程环境中保证对变量的修改不会引起竞态条件。

CAS 操作

CAS 操作涉及三个值:

  1. 内存位置(V):需要读取和更新的变量。
  2. 预期值(A):当前线程认为变量应该持有的值。
  3. 新值(B):线程希望将变量的值更新为的新值。

CAS 过程如下:

  • 检查内存位置 V 的当前值是否等于预期值 A。
  • 如果相等,则将内存位置 V 的值更新为新值 B。
  • 如果不相等,则不进行任何操作并返回当前值。

这个过程是一个原子操作,不会被其他线程中断。

AtomicInteger 实现原理

在 Java 中,AtomicInteger 类使用 CAS 操作来实现其方法。以下是它的一些关键方法及其实现原理:

incrementAndGet()

这是 AtomicInteger 类中一个常用方法,用于以原子方式将当前值加 1,并返回加 1 后的值。

java 复制代码
public final int incrementAndGet() {
    for (;;) {
        int current = get();
        int next = current + 1;
        if (compareAndSet(current, next))
            return next;
    }
}

解释:

  1. 获取当前值 :调用 get() 方法获取当前值。
  2. 计算下一个值:将当前值加 1,得到下一个值。
  3. CAS 操作 :调用 compareAndSet(current, next) 尝试将当前值更新为下一个值。
    • 如果当前值等于预期值(current),则更新成功,返回更新后的值。
    • 如果当前值不等于预期值,则表示在这段时间内已经有其他线程修改了当前值。因此,循环重试,直到更新成功。
compareAndSet(int expect, int update)

这是一个本地方法(native),通常由 JVM 底层通过硬件指令实现。

java 复制代码
public final boolean compareAndSet(int expect, int update) {
    return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}

解释:

  1. unsafe :使用了 Unsafe 类,这是一个提供底层操作的类。Unsafe 类允许进行低级别的、不受限制的内存操作。
  2. compareAndSwapInt:这是一个本地方法,使用底层的硬件指令来执行 CAS 操作。

为什么 AtomicInteger 是原子的

由上述实现原理可以看出,AtomicInteger 的操作是原子的,原因主要有以下几点:

  1. CAS 操作:底层的 CAS 操作保证了整个比较和交换步骤的原子性。
  2. 硬件支持:现代处理器通常提供对 CAS 操作的原生支持,这样可以确保这些操作在硬件级别上是原子的。
  3. 循环重试:如果 CAS 操作失败(因为其他线程修改了值),AtomicInteger 会自动进行循环重试,直到操作成功。

因此,AtomicInteger 能够在多线程环境中安全地进行整数操作,避免传统锁机制带来的性能损耗,同时确保操作的正确性。

相关推荐
南山十一少3 小时前
Spring Security+JWT+Redis实现项目级前后端分离认证授权
java·spring·bootstrap
427724004 小时前
IDEA使用git不提示账号密码登录,而是输入token问题解决
java·git·intellij-idea
chengooooooo5 小时前
苍穹外卖day8 地址上传 用户下单 订单支付
java·服务器·数据库
李长渊哦5 小时前
常用的 JVM 参数:配置与优化指南
java·jvm
计算机小白一个5 小时前
蓝桥杯 Java B 组之设计 LRU 缓存
java·算法·蓝桥杯
南宫生8 小时前
力扣每日一题【算法学习day.132】
java·学习·算法·leetcode
计算机毕设定制辅导-无忧学长8 小时前
Maven 基础环境搭建与配置(一)
java·maven
风与沙的较量丶9 小时前
Java中的局部变量和成员变量在内存中的位置
java·开发语言
m0_748251729 小时前
SpringBoot3 升级介绍
java
极客先躯10 小时前
说说高级java每日一道面试题-2025年2月13日-数据库篇-请说说 MySQL 数据库的锁 ?
java·数据库·mysql·数据库的锁·模式分·粒度分·属性分