Java高频面试之并发编程-27

hello啊,各位观众姥爷们!!!本baby今天又来报道了!哈哈哈哈哈嗝🐶

面试:详细说说AtomicInteger 的原理


AtomicInteger 的原理详解
AtomicInteger 是 Java 并发包 (java.util.concurrent.atomic) 中的原子类,用于实现 线程安全的整型变量操作(如 i++),其核心原理基于 CAS(Compare and Swap) 无锁算法和 volatile 可见性。以下是其实现原理的详细分析:


1. 核心设计

(1) 依赖的底层技术
  • CAS 操作:通过 sun.misc.Unsafe 类调用 CPU 的原子指令(如 CMPXCHG),实现无锁的原子更新。
  • volatile 变量:内部值 valuevolatile 修饰,保证多线程间的可见性(直接读写主内存)。
(2) 类结构关键代码
public class AtomicInteger extends Number implements java.io.Serializable {private static final long serialVersionUID = 6214790243416807050L;// 使用 Unsafe 类操作底层 CASprivate static final Unsafe unsafe = Unsafe.getUnsafe();private static final long valueOffset; // value 字段的内存偏移量static {try {// 获取 value 字段在对象内存中的偏移量valueOffset = unsafe.objectFieldOffset(AtomicInteger.class.getDeclaredField("value"));} catch (Exception ex) { throw new Error(ex); }}private volatile int value; // 实际存储值的 volatile 变量public AtomicInteger(int initialValue) {value = initialValue;}
}

2. 关键方法实现原理

(1) incrementAndGet():原子自增
public final int incrementAndGet() {return unsafe.getAndAddInt(this, valueOffset, 1) + 1;
}// Unsafe 类的实现
public final int getAndAddInt(Object o, long offset, int delta) {int v;do {v = getIntVolatile(o, offset); // 读取当前值} while (!compareAndSwapInt(o, offset, v, v + delta)); // CAS 更新return v;
}

步骤

  1. 读取当前值:通过 getIntVolatile 读取 value 的当前值(volatile 保证可见性)。
  2. CAS 更新:尝试用 compareAndSwapIntvaluev 更新为 v + delta
  3. 失败重试:若 CAS 失败(值已被其他线程修改),循环重试直到成功。
(2) compareAndSet():CAS 核心方法
public final boolean compareAndSet(int expect, int update) {return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}
  • 若当前值等于 expect,则将其更新为 update,返回 true;否则返回 false
(3) get()set():直接访问 volatile 变量
public final int get() {return value; // 直接读取 volatile 变量,保证可见性
}public final void set(int newValue) {value = newValue; // 直接写入 volatile 变量
}

3. 无锁设计的优势

(1) 高性能
  • 无阻塞:线程通过自旋(循环重试)而非阻塞等待,减少上下文切换开销。
  • 低竞争时高效:在低并发场景下,CAS 成功率极高,性能远超 synchronizedReentrantLock
(2) 避免死锁
  • 无锁机制天然避免死锁,因为没有线程会持有锁不放。

4. 局限性及应对

(1) ABA 问题
  • 问题描述:若变量的值从 A 改为 B 后又改回 A,CAS 无法感知中间变化。
  • 解决方案:使用 AtomicStampedReferenceAtomicMarkableReference,通过版本号标记状态。
    AtomicStampedReference<Integer> ref = new AtomicStampedReference<>(0, 0);
    ref.compareAndSet(0, 1, 0, 1); // 检查值 + 版本号
    
(2) 自旋开销
  • 问题:高并发下 CAS 失败率高,线程长时间自旋浪费 CPU。
  • 优化策略
    • 退避算法:失败后等待一段时间再重试(如 Thread.yield())。
    • 结合锁机制:在自旋一定次数后转为阻塞锁。
(3) 仅支持单一变量
  • 问题:无法原子更新多个变量(如 i++j++ 需同时保证原子性)。
  • 解决方案
    • 使用 AtomicReference 封装多个变量为一个对象。
    • 对复合操作使用锁(如 synchronized)。

5. 性能对比

AtomicInteger vs synchronized vs ReentrantLock
场景AtomicIntegersynchronizedReentrantLock
低竞争极快(无锁自旋)较快(偏向锁优化)较快(CAS 尝试)
高竞争较差(自旋开销大)较差(线程阻塞频繁)较差(CAS 竞争激烈)
复合操作不支持支持支持

6. 应用场景

  • 计数器:如统计请求量、在线人数。
  • 状态标志:如开关状态的原子切换。
  • 序列生成:生成唯一递增 ID。

总结

AtomicInteger 通过 CAS + volatile 实现了无锁的线程安全操作:

  1. CAS:保证原子性,避免锁开销。
  2. volatile:保证可见性,确保线程读取最新值。
  3. 自旋重试:在竞争不激烈时高效,高竞争时需结合退避策略。

你想要的技术资料我全都有:https://pan.q删掉汉子uark.cn/s/aa7f2473c65b
在这里插入图片描述

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

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

相关文章

冒险岛的魔法果实-多重背包

问题描述 在冒险岛的深处&#xff0c;小萌探索到了一个传说中的魔法果实园。这里满是各种神奇的魔法果实&#xff0c;吃了可以增加不同的魔法能量。 小萌想带一些魔法果实回去&#xff0c;但是他的背包空间有限。看着这些琳琅满目的魔法果实&#xff0c;小萌很是纠结&#xf…

atomicity of memory accesses

文章目录 atomicity of memory accesses✅ 正确认识原子性的边界对于 **Load**&#xff1a;✅ 正确的原子性边界是&#xff1a;对于 **Store**&#xff1a;✅ 正确的原子性边界是&#xff1a; &#x1f504; 修正原文中的说法&#xff08;对照分析&#xff09;✅ 原子性边界最终…

VScode安装配置PYQT6

开始是准备安装PYQT5的&#xff0c;但是安装不下去&#xff0c;就改成安装PYQT6 一.安装pyqt5&#xff0c;成功。 c:\PYQT>pip install pyqt5 Defaulting to user installation because normal site-packages is not writeable Collecting pyqt5 Downloading PyQt5-5.15.…

SpringBoot使用oshi获取服务器相关信息

概念 OSHI是Java的免费基于JNA的&#xff08;本机&#xff09;操作系统和硬件信息库。它不需要安装任何其他本机库&#xff0c;并且旨在提供一种跨平台的实现来检索系统信息&#xff0c;例如操作系统版本&#xff0c;进程&#xff0c;内存和CPU使用率&#xff0c;磁盘和分区&a…

Spring Boot 3 集成 MyBatis 连接 MySQL 数据库

Spring Boot 3 集成 MyBatis 连接 MySQL 数据库的步骤&#xff1a; 以下是集成 Spring Boot 3、MyBatis、HikariCP 连接池并操作 MySQL 数据库的完整步骤和代码&#xff1a; 一、创建 Spring Boot 项目 添加以下依赖&#xff1a; <dependencies><!-- Spring Web --…

基于React + FastAPI + LangChain + 通义千问的智能医疗问答系统

&#x1f4cc; 文章摘要&#xff1a; 本文详细介绍了如何在前端通过 Fetch 实现与 FastAPI 后端的 流式响应通信&#xff0c;并支持图文多模态数据上传。通过构建 multipart/form-data 请求&#xff0c;配合 ReadableStream 实时读取 AI 回复内容&#xff0c;实现类似 ChatGPT…

YOLOv8 升级之路:主干网络嵌入 SCINet,优化黑暗环境目标检测

文章目录 引言1. 低照度图像检测的挑战1.1 低照度环境对目标检测的影响1.2 传统解决方案的局限性2. SCINet网络原理2.1 SCINet核心思想2.2 网络架构3. YOLOv8与SCINet的集成方案3.1 总体架构设计3.2 关键集成代码3.3 训练策略4. 实验结果与分析4.1 实验设置4.2 性能对比4.3 可视…

所有的Linux桌面环境

Linux操作系统提供了多种桌面环境&#xff0c;每种都有其独特的特点和适用场景。以下是一些常见的Linux桌面环境&#xff1a; 轻量级桌面环境 Xfce&#xff1a;广泛使用的轻量级桌面环境&#xff0c;适合资源有限的设备。Xfce 4.18带来了性能改进和新功能&#xff0c;如Thuna…

@component、@bean、@Configuration的区别

详细解析Spring框架中这三个最核心、也最容易混淆的注解&#xff1a;Component、Bean和Configuration。 为了快速理解&#xff0c;我们先看一个总结性的表格&#xff1a; 注解应用级别作用使用场景Component类级别将类标识为Spring组件&#xff0c;让Spring自动扫描并创建实例…

Android多媒体——音/视同步数据处理(二十)

在多媒体播放过程中,音频数据的处理不仅要保证其解码和输出的连续性,还需要与视频帧保持时间上的严格对齐,以实现良好的观看体验。Android 多媒体框架中的 NuPlayerRenderer 是负责最终渲染音视频数据的核心组件之一。 一、Audio数据处理 NuPlayerRenderer 是 Android 原生…

MYSQL 使用命令mysqldump备份数据库的时候需要用户具备什么权限

背景 之前都是使用数据库root用户备份数据库&#xff0c;没有权限问题&#xff0c;今天使用一个数据库基本用户备份数据库&#xff0c;提示一直没有权限&#xff0c;提示的很明显 mysqldump: Error: Access denied; you need (at least one of) the PROCESS privilege(s) for …

WebRTC源码线程-1

1、概述 本篇主要是简单介绍WebRTC中的线程&#xff0c;WebRTC源码对线程做了很多的封装。 1.1 WebRTC中线程的种类 1.1.1 信令线程 用于与应用层的交互&#xff0c;比如创建offer&#xff0c;answer&#xff0c;candidate等绝大多数的操作 1.1.2 工作线程 负责内部的处理逻辑&…

spring:使用标签xml静态工厂方法获取bean

在spring可以直接通过配置文件获取bean对象&#xff0c;如果获取的bean对象还有若干设置&#xff0c;需要自动完成&#xff0c;可以通过工厂方法获取bean对象。 静态工厂类&#xff0c;其中InterfaceUserDao和InterfaceUserService都是自定义的接口&#xff0c;可以自己替换。…

linux 用户态时间性能优化工具perf/strace/gdb/varlind/gprof

1. perf top -g或者top分析卡顿(cpu占用比较高的函数) gdb 是 GNU 调试器,可以用于分析程序的时间性能。虽然 info time 不是直接用于性能分析的命令,但 gdb 提供了与时间相关的功能,例如通过 timer 命令设置计时器或通过 info proc 查看进程的时间信息。 #include <…

客户端和服务器已成功建立 TCP 连接【输出解析】

文章目录 图片**1. 连接状态解析****第一条记录&#xff08;服务器监听&#xff09;****第二条记录&#xff08;客户端 → 服务器&#xff09;****第三条记录&#xff08;服务器 → 客户端&#xff09;** **2. 关键概念澄清****(1) 0.0.0.0 的含义****(2) 端口号的分配规则** *…

Win系统下的Linux系统——WSL 使用手册

我们在复现一些项目的时候&#xff0c;有些依赖包只能在 linux 环境下使用&#xff0c;还不打算使用远程服务器&#xff0c;那么此时我们可以使用 WSL 创建一个 ubutu 系统&#xff0c;在这个系统里创建虚拟环境、下载依赖包。然后&#xff0c;我们就可以在 windows 下的 vscod…

电脑同时连接内网和外网的方法,附外网连接局域网的操作设置

对于工作一般都设置在内网网段中&#xff0c;而同时由于需求需要连接外网&#xff0c;一般只能通过内网和外网的不断切换进行设置&#xff0c;如果可以同时连接内网和外网会更加便利&#xff0c;同时连接内网和外网方法具体如下。 一、电脑怎么弄可以同时连接内网和外网&#…

C++11:原子操作与内存顺序:从理论到实践的无锁并发实现

文章目录 0.简介1.并发编程需要保证的特性2.原子操作2.1 原子操作的特性 3.内存顺序3.1 顺序一致性3.2 释放-获取&#xff08;Release-Acquire)3.3 宽松顺序&#xff08;Relaxed)3.4 内存顺序 4.无锁并发5. 使用建议 0.简介 在并发编程中&#xff0c;原子性、可见性和有序性是…

oracle 归档日志与RECOVERY_FILE_DEST 视图

1. RECOVERY_FILE_DEST 视图的作用 RECOVERY_FILE_DEST 是 Oracle 数据库用于 管理快速恢复区&#xff08;Fast Recovery Area, FRA&#xff09; 的一个视图。FRA 是 Oracle 提供的一种集中存储恢复相关文件&#xff08;如归档日志、备份文件、闪回日志等&#xff09;的区域。…

零基础玩转物联网-串口转以太网模块如何快速实现与MQTT服务器通信

目录 1 前言 2 环境搭建 2.1 硬件准备 2.2 软件准备 2.3 驱动检查 3 MQTT服务器通信配置与交互 3.1 硬件连接 3.2 开启MQTT服务器 3.3 打开配置工具读取基本信息 3.4 填写连接参数进行连接 3.5 通信测试 4 总结 1 前言 MQTT&#xff1a;全称为消息队列遥测传输协议&#xff08;…