java中应使用atomiclong而非long实现线程安全的long值修改,因其基于cas提供无锁原子操作;long不可变且非原子,同步块模拟低效易错;atomiclong需new初始化、用get/set/incrementandget等方法操作,不可与long混用。

Java 中 Long 是不可变的包装类,每次修改(如 l = l + 1)都会创建新对象,无法保证原子性。要实现线程安全的 long 值修改,应直接使用 AtomicLong,它基于 CAS(Compare-and-Swap)提供无锁原子操作。
用 AtomicLong 替代 Long 的基本写法
AtomicLong 封装了一个 long 值,所有读写和更新操作都是原子的。不要用 Long 变量加同步块去模拟,那是低效且易出错的。
- 声明:用
new AtomicLong(0)初始化,而非Long.valueOf(0) - 读值:调用
get(),不是直接取变量 - 写值:用
set(long newValue),不是赋值语句 - 自增/自减:优先用
incrementAndGet()或decrementAndGet(),它们返回新值;若只需执行动作不关心结果,可用getAndIncrement()
常见原子更新操作对照表
下面列出 Long 常见非原子操作,及其在 AtomicLong 中的等价、线程安全写法:
-
l++→atomicLong.incrementAndGet() -
l += 5→atomicLong.addAndGet(5) -
l = Math.max(l, 100)→ 用循环 CAS 实现:long current; long update;<br>do {<br> current = atomicLong.get();<br> update = Math.max(current, 100);<br>} while (!atomicLong.compareAndSet(current, update)); - 条件更新(如仅当当前值为 0 时设为 1)→
atomicLong.compareAndSet(0, 1)
注意包装类与 AtomicLong 的本质区别
Long 是值对象,AtomicLong 是可变容器。二者不能混用:
- 别把
AtomicLong当作Long传参:方法参数是Long类型时,需显式调用atomicLong.get()转换 - 别误以为
AtomicLong.valueOf(123)是构造方式——它只是缓存池获取(类似Long.valueOf),应始终用new AtomicLong(123) - 没有
AtomicLong的自动拆箱;if (atomicLong > 0)编译不过,必须写成if (atomicLong.get() > 0)
何时仍需 Long?
AtomicLong 解决的是「共享状态的并发修改」问题。如果变量只在单线程内使用、或作为不可变配置值传递,Long 更轻量、语义更清晰。例如方法返回值、Stream 中的 map 结果、JSON 序列化的字段,依然用 Long 即可。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











