0

0

在Java里如何使用Atomic类实现无锁并发_Java原子操作原理说明

P粉602998670

P粉602998670

发布时间:2026-01-20 13:01:02

|

489人浏览过

|

来源于php中文网

原创

atomicinteger 更轻量因基于cas指令,避免线程挂起与上下文切换;但高竞争下重试耗cpu,适用于计数器等简单操作,不适用复合逻辑。

在java里如何使用atomic类实现无锁并发_java原子操作原理说明

AtomicInteger 为什么比 synchronized 更轻量

因为 AtomicInteger 底层调用的是 CPU 提供的 CAS(Compare-And-Swap)指令,不涉及操作系统线程挂起/唤醒,避免了锁带来的上下文切换开销。但要注意:CAS 在高竞争下会不断重试,反而可能比锁更耗 CPU。

典型适用场景是计数器、状态标志位这类简单读-改-写操作,比如秒杀库存扣减、请求统计。不适合复合逻辑(如“先读再判断再更新”),那得用 synchronizedReentrantLock

常见错误是误以为 incrementAndGet() 能替代所有同步场景——它只保证单个原子操作,不保证多个原子操作之间的顺序或可见性组合。

getAndIncrement 和 incrementAndGet 的区别在哪

两者都执行“加 1 并返回旧值”或“加 1 并返回新值”,但语义和返回值不同:

立即学习Java免费学习笔记(深入)”;

  • getAndIncrement() 返回自增前的值(类似 i++
  • incrementAndGet() 返回自增后的值(类似 ++i

性能上无差别,选哪个纯看业务需要。例如生成唯一 ID 时常用 incrementAndGet(),而做轮询索引时可能用 getAndIncrement() 避免额外减 1。

注意:它们都不是“线程安全的 ++ 运算符替代品”——Java 中没有原生的原子 ++ 操作符,必须显式调用这些方法。

AtomicReference 用错引用比较会出什么问题

AtomicReferencecompareAndSet(expected, updated) 是按引用地址比较(==),不是按内容(.equals())。如果传入一个新构造的对象作为 expected,即使字段值相同,也会失败。

常见踩坑点:

  • new String("abc") 作期望值,而当前值是字符串常量池里的 "abc"
  • 在循环中反复 new 对象用于 compareAndSet,导致永远无法匹配
  • 误以为它能自动处理对象内部字段的原子更新(不能,要用 AtomicReferenceFieldUpdaterVarHandle
AtomicReference<String> ref = new AtomicReference<>("hello");
// ❌ 错误:new String 创建新对象,引用不同
ref.compareAndSet(new String("hello"), "world"); // 返回 false

// ✅ 正确:复用原引用或使用 intern()
ref.compareAndSet("hello", "world"); // 返回 true

AtomicLongArray 在批量计数时怎么避免伪共享

多核 CPU 缓存以 cache line(通常 64 字节)为单位加载数据。AtomicLongArray 的相邻元素若落在同一 cache line,会导致不同线程更新不同下标时相互干扰(false sharing),性能骤降。

解决方式不是换工具,而是结构对齐:

  • 手动 padding:每个 long 后填充 7 个 long,确保每个有效元素独占 cache line(但浪费内存)
  • jdk.internal.vm.annotation.Contended(JDK 8+,需开启 -XX:-RestrictContended
  • 更实际的做法是:避免高频更新密集下标;或改用分段计数(如 LongAdder,它内部就用了类似 padding 的策略)

LongAdderAtomicLong 更适合高并发累加场景,但它不是“更高级的 AtomicLong”,而是牺牲了实时一致性来换吞吐——它的 sum() 不是强一致的。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

970

2023.08.02

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1561

2023.10.24

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1561

2023.10.24

Go语言中的运算符有哪些
Go语言中的运算符有哪些

Go语言中的运算符有:1、加法运算符;2、减法运算符;3、乘法运算符;4、除法运算符;5、取余运算符;6、比较运算符;7、位运算符;8、按位与运算符;9、按位或运算符;10、按位异或运算符等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

241

2024.02.23

php三元运算符用法
php三元运算符用法

本专题整合了php三元运算符相关教程,阅读专题下面的文章了解更多详细内容。

128

2025.10.17

字符串常量的表示方法
字符串常量的表示方法

字符串常量的表示方法:1、使用引号;2、转义字符;3、多行字符串;4、原始字符串;5、字符串连接;6、字符串字面量和对象;7、编码问题。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

143

2023.12.26

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

738

2023.08.03

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

219

2023.09.04

JavaScript浏览器渲染机制与前端性能优化实践
JavaScript浏览器渲染机制与前端性能优化实践

本专题围绕 JavaScript 在浏览器中的执行与渲染机制展开,系统讲解 DOM 构建、CSSOM 解析、重排与重绘原理,以及关键渲染路径优化方法。内容涵盖事件循环机制、异步任务调度、资源加载优化、代码拆分与懒加载等性能优化策略。通过真实前端项目案例,帮助开发者理解浏览器底层工作原理,并掌握提升网页加载速度与交互体验的实用技巧。

23

2026.03.06

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Kotlin 教程
Kotlin 教程

共23课时 | 4.2万人学习

C# 教程
C# 教程

共94课时 | 10.9万人学习

Java 教程
Java 教程

共578课时 | 78.6万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号