0

0

Atomic原子类是如何实现线程安全的_并发工具类入门

P粉602998670

P粉602998670

发布时间:2026-01-08 14:19:45

|

529人浏览过

|

来源于php中文网

原创

Atomic类通过CAS实现无锁原子性,依赖CPU底层指令保证“读-判-写”不可分割,适用于纯内存简单状态变更;不适用于复合操作、I/O或跨变量约束场景。

atomic原子类是如何实现线程安全的_并发工具类入门

Atomic类靠CAS实现无锁原子性,不是靠synchronized或Lock

Atomic类(如AtomicInteger)的线程安全,根本不是加锁来的。它依赖CPU提供的底层原子指令——CAS(Compare-And-Swap),在硬件层面保证“读-判-写”三步不可分割。只要当前值等于预期值,就原子地更新为新值;否则失败并返回false,由调用方决定重试或放弃。

  • compareAndSet(int expect, int update)是核心方法,所有其他操作(如incrementAndGet())最终都基于它循环尝试
  • 没有线程阻塞,没有上下文切换开销,高并发下吞吐量明显优于synchronized
  • 但要注意:CAS成功 ≠ 业务逻辑成功——比如多个线程同时对计数器+1,结果一定正确;但若+1前还要查数据库校验余额,CAS就管不了这层语义了

什么时候该用AtomicInteger而不是int + synchronized?

典型场景是「纯内存状态变更」且操作足够简单:计数器、开关标志、序列号生成、引用计数等。一旦涉及I/O、多变量协同、条件分支依赖共享状态,就该退回到锁或更高级并发结构。

  • ✅ 推荐用AtomicIntegerlikeCount.incrementAndGet()统计点赞数
  • ✅ 推荐用AtomicBooleanrunning.compareAndSet(true, false)安全关闭轮询线程
  • ❌ 别硬套:if (counter.get() > 100) counter.set(0) —— 这里存在竞态窗口,应改用getAndUpdate()或锁
  • ⚠️ 注意初始值:不显式传参时默认为0,但new AtomicInteger(-1)这种非零初始化很常见,别漏掉

compareAndSet失败后怎么办?别直接抛异常或忽略

compareAndSet()返回false不是异常,而是明确告诉你“值已被别人改了”。这时候不能沉默,也不能粗暴重试无限循环(可能饿死CPU),得结合业务做合理兜底。

lavender.ai
lavender.ai

销售类电子邮件写作教练

下载
  • 常见做法是用getAndUpdate()updateAndGet()——它们内部已封装了CAS自旋逻辑,语义更清晰
  • 若需复杂判断(比如“仅当旧值为X且满足Y条件才更新”),建议用getAndAccumulate()配合IntBinaryOperator
  • 极端低延迟场景下,可考虑lazySet()代替set():它不保证立即可见,但写入更快,适合发布状态标记(如done.lazySet(true)
  • 警惕ABA问题:如果一个值从A→B→A,CAS会误认为没变。JDK提供了AtomicStampedReference带版本戳解决,但多数计数类场景无需考虑

Atomic类不是万能的,别把它当“线程安全银弹”

它只保单个变量的原子读写,不保复合操作、不保可见性传播、不保跨变量约束。比如两个AtomicInteger相加再存入第三个,这个“加+存”整体仍非原子。

  • 多个原子变量之间无顺序保证:线程1执行a.set(1); b.set(2),线程2可能看到a==1 && b==0(因JVM和CPU重排序)
  • 想让多变量操作强一致?要么上锁,要么用AtomicReference把多个字段包进一个不可变对象里整体更新
  • 局部变量永远线程安全,别为了“看起来统一”而滥用Atomic——int local = x.get() + y.get();AtomicInteger local = new AtomicInteger(x.get() + y.get());干净得多

真正容易被忽略的是:Atomic类只解决原子性,不自动解决可见性和有序性边界。哪怕用了AtomicInteger,如果在它之后立刻读一个普通int字段,那个读操作仍可能看不到最新值——该加volatile还得加,该同步代码块还得同步。

相关专题

更多
if什么意思
if什么意思

if的意思是“如果”的条件。它是一个用于引导条件语句的关键词,用于根据特定条件的真假情况来执行不同的代码块。本专题提供if什么意思的相关文章,供大家免费阅读。

724

2023.08.22

string转int
string转int

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

315

2023.08.02

int占多少字节
int占多少字节

int占4个字节,意味着一个int变量可以存储范围在-2,147,483,648到2,147,483,647之间的整数值,在某些情况下也可能是2个字节或8个字节,int是一种常用的数据类型,用于表示整数,需要根据具体情况选择合适的数据类型,以确保程序的正确性和性能。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

532

2024.08.29

c++怎么把double转成int
c++怎么把double转成int

本专题整合了 c++ double相关教程,阅读专题下面的文章了解更多详细内容。

51

2025.08.29

C++中int的含义
C++中int的含义

本专题整合了C++中int相关内容,阅读专题下面的文章了解更多详细内容。

193

2025.08.29

c++中volatile关键字的作用
c++中volatile关键字的作用

本专题整合了c++中volatile关键字的相关内容,阅读专题下面的文章了解更多详细内容。

67

2025.10.23

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

478

2023.08.10

数据库三范式
数据库三范式

数据库三范式是一种设计规范,用于规范化关系型数据库中的数据结构,它通过消除冗余数据、提高数据库性能和数据一致性,提供了一种有效的数据库设计方法。本专题提供数据库三范式相关的文章、下载和课程。

341

2023.06.29

c++主流开发框架汇总
c++主流开发框架汇总

本专题整合了c++开发框架推荐,阅读专题下面的文章了解更多详细内容。

22

2026.01.09

热门下载

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

精品课程

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

共58课时 | 3.5万人学习

Pandas 教程
Pandas 教程

共15课时 | 0.9万人学习

ASP 教程
ASP 教程

共34课时 | 3.4万人学习

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

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