atomicinteger 通过 cas 指令和 volatile 语义实现无锁线程安全:cas 保证“读—比—写”原子性并自动重试,volatile 确保内存可见性;适用于单变量原子操作,高冲突场景需谨慎使用。

直接用 AtomicInteger 替代普通 int 变量,调用 incrementAndGet()、addAndGet() 等内置原子方法,就能在不加锁的前提下保证线程安全,同时避免锁带来的上下文切换和阻塞开销。
为什么原子类能避开锁又保持线程安全
AtomicInteger 底层依赖两个关键机制:
- CAS 指令(Compare-And-Swap):这是 CPU 提供的硬件级原子操作。每次更新前先读取当前值(V),比对是否仍为预期值(A),只有相等才写入新值(B)。整个“读—比—写”过程不可分割,失败则自动重试,无需挂起线程。
- volatile 语义:内部变量被 volatile 修饰,确保每次读取都从主内存获取最新值,每次写入都立即刷新到主内存,彻底解决缓存不一致导致的脏读问题。
常用原子操作方法及适用场景
不用自己写循环 CAS,JDK 已封装好高可用接口:
-
incrementAndGet():自增后返回新值,适合计数器累加(如请求统计) -
decrementAndGet():自减后返回新值,适合资源配额扣减 -
addAndGet(delta):加指定数值后返回结果,适合批量调整 -
compareAndSet(expected, newvalue):手动控制条件更新,适合状态机切换(如从 INIT → RUNNING) -
lazySet(newValue):弱可见性写入,适合单写多读且不要求实时可见的场景(如心跳状态标记),性能略优于set()
使用时要注意的关键细节
原子类不是万能银弹,需结合场景合理选用:
- 仅适用于单个变量的原子操作;多个字段联动更新(如“余额扣减 + 订单状态变更”)仍需加锁或事务协调
- CAS 在高冲突场景下会频繁重试,可能带来 CPU 浪费;若写操作占比超过 20%,应评估是否改用
ReentrantLock或分段计数(如LongAdder) - 避免把
get()和后续逻辑组成“读—改—写”伪原子块,这仍是竞态点;必须用compareAndSet()或复合方法(如accumulateAndGet())保证整体原子性 - 注意 ABA 问题:某值从 A→B→A,CAS 会误判成功;若业务敏感(如版本号、引用对象回收),应改用
AtomicStampedReference
对比传统加锁的典型性能差异
在 100 个线程并发执行 10 万次自增的测试中:
- synchronized 同步块:平均耗时约 85–110ms,存在明显线程排队和上下文切换
- ReentrantLock:平均耗时约 70–95ms,支持更多控制但仍有锁开销
- AtomicInteger.incrementAndGet():平均耗时约 25–40ms,无阻塞、无调度延迟
差距主要来自锁机制需要操作系统介入调度,而 CAS 是纯用户态指令,只要竞争不激烈,性能优势非常显著。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











