登录
首页 >  Golang >  Go教程

Atomic包6种原子操作全解析

时间:2026-01-30 12:45:44 153浏览 收藏

“纵有疾风来,人生不言弃”,这句话送给正在学习Golang的朋友们,也希望在阅读本文《Atomic包的6种原子操作你都掌握了吗?》后,能够真的帮助到大家。我也会在后续的文章中,陆续更新Golang相关的技术文章,有好的建议欢迎大家在评论留言,非常感谢!

Atomic包核心在于“用对场景”:6种原子类各解决特定并发问题,混淆使用易引入bug;需依场景选型,避免误当通用同步工具。

atomic 包的6种原子操作你真的都会用吗?

Atomic 包的核心不是“会用”,而是“用对场景”。6 种原子类(AtomicIntegerAtomicLongAtomicBooleanAtomicReferenceAtomicStampedReferenceAtomicMarkableReference)各自解决一类并发问题,混淆使用反而引入 bug。

基础数值型:别当普通变量用

AtomicIntegerAtomicLong 适合计数器、序列号生成等简单累加/递减场景。它们的 incrementAndGet()compareAndSet(expected, updated) 是线程安全的核心,但要注意:
– 不支持复合运算(如 i += 2),必须拆成 get + compute + compareAndSet 循环重试;
– 高频更新下,CAS 失败重试可能引发“自旋开销”,此时应考虑 LongAdder(JDK8+)替代;
– 初始值设为 0 并不总是合理,比如分布式 ID 生成器需从特定偏移开始。

AtomicBoolean:真不是 boolean 的线程安全版

它本质是封装了 int 值(0/1)的 CAS 操作,适用于状态开关(如“是否已初始化”、“是否已关闭”)。关键点:
getAndSet(true) 可实现“抢占式置位并获知原状态”,比先 get 再 set 更可靠;
– 不要把它当成可多次切换的 flag 来做复杂状态机——缺乏内存语义保障,多状态建议用 AtomicReference + 枚举;
lazySet(false) 可避免写屏障开销,适合只关心最终一致性的关闭信号。

AtomicReference:引用安全的起点,不是万能容器

它保证引用本身的读写原子性,但不保证对象内部字段线程安全。典型用法:
– 实现无锁栈、队列(如 Treiber Stack);
– 封装不可变对象(如配置快照)供多线程读取;
– 配合 UnsafeVarHandle 实现更细粒度控制(需谨慎);
– 注意:若引用的对象可变(如 AtomicReference),add() 等操作仍需外部同步。

带版本/标记的引用:专治 ABA 问题

AtomicStampedReferenceAtomicMarkableReference 解决的是“值相同但中间被改过”的 ABA 问题,但它们不是通用解法:
AtomicStampedReference 用整数戳记(stamp),适合需要区分“第几次修改”的场景(如乐观锁重试计数);
AtomicMarkableReference 用布尔标记,常用于标记“逻辑删除”(如链表节点标记为已删,后续清理);
– stamp 和 mark 本身不自动增长,需业务代码维护;
– 过度依赖戳记可能掩盖设计缺陷——真正该重构的是共享状态的粒度或生命周期管理。

小结:Atomic 类不是 synchronized 的替代品,也不是性能银弹。用错比不用更危险——比如用 AtomicInteger 存用户余额,看似线程安全,却漏掉了扣款前的余额校验和事务一致性。

好了,本文到此结束,带大家了解了《Atomic包6种原子操作全解析》,希望本文对你有所帮助!关注golang学习网公众号,给大家分享更多Golang知识!

前往漫画官网入口并下载 ➜
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>