如何在Golang中使用sync/atomic实现原子操作_安全并发计数

发布时间 - 2026-01-05 00:00:00    点击率:
Go 中 sync/atomic 通过底层 CPU 原子指令实现无锁高性能计数,比 mutex 更轻量高效;仅支持基础类型原子操作,需取地址调用且避免与普通赋值混用。

在 Go 中,sync/atomic 是实现无锁、高性能并发计数的核心工具。它直接映射到底层 CPU 的原子指令(如 LOCK XADD),比加锁更轻量,适合高频读写计数器场景。

为什么用 atomic 而不是 mutex?

使用 sync.Mutex 保护一个整型计数器虽然安全,但每次增减都要获取/释放锁,存在调度开销和竞争排队;而 atomic 操作是单条 CPU 指令,无上下文切换,吞吐更高。尤其在多核高并发下,性能差距明显。

注意:atomic 只支持基础类型(int32, int64, uint32, uint64, uintptr, *unsafe.Pointer)及其指针操作,不能用于结构体或 map 等复合类型。

基础计数器:增减与读取

声明计数器时必须用支持原子操作的类型(推荐 int64,避免 32 位平台对齐问题),并确保变量地址对齐(全局变量或堆分配自动满足):

立即学习“go语言免费学习笔记(深入)”;

✅ 正确示例:

  • 定义:var counter int64(全局或包级变量)
  • 原子自增:atomic.AddInt64(&counter, 1)
  • 原子读取:atomic.LoadInt64(&counter)
  • 原子写入:atomic.StoreInt64(&counter, 100)
  • 条件更新(CAS):atomic.CompareAndSwapInt64(&counter, old, new),仅当当前值等于 old 时才设为 new,返回是否成功

常见陷阱与规避方式

— 计数器必须取地址传递给 atomic 函数,传值会报编译错误;
— 不要混用 atomic 和普通赋值(如 counter = 42),这会破坏原子性;
— 避免在非对齐内存上使用(如 struct 中未导出的 int32 字段紧邻其他字段),可能导致 panic(尤其在 ARM 上);
atomic.Value 用于安全读写任意类型(如 map[string]int),但它不提供原子增减,只做整体替换。

完整可运行示例

以下是一个启动 10 个 goroutine 并发累加 1000 次的计数器:

package main

import (
    "fmt"
    "sync"
    "sync/atomic"
    "time"
)

func main() {
    var counter int64
    var wg sync.WaitGroup

    for i := 0; i < 10; i++ {
        wg.Add(1)
        go func() {
            defer wg.Done()
            for j := 0; j < 1000; j++ {
                atomic.AddInt64(&counter, 1)
            }
        }()
    }

    wg.Wait()
    fmt.Println("Final count:", atomic.LoadInt64(&counter)) // 输出 10000
}

若换成普通 counter++ 且无锁,结果大概率小于 10000 —— 这正是竞态的典型表现。


# go  # golang  # 工具  # ai  # 编译错误  # 无锁  # 为什么  # String  # 整型  # 全局变量  # 结构体  # int  # 指针  #   # Struct  # var  # pointer  # map  # 并发  # 多核  # 会报  # 高性能  # 是一个  # 都要  # 设为  # 更高  # 它不  # 时才  # 只做 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: 简单实现Android验证码  php485函数参数是什么意思_php485各参数详细说明【介绍】  如何用ChatGPT准备面试 模拟面试问答与职场话术练习教程  Android Socket接口实现即时通讯实例代码  如何快速搭建高效香港服务器网站?  Laravel怎么使用Intervention Image库处理图片上传和缩放  iOS UIView常见属性方法小结  如何用搬瓦工VPS快速搭建个人网站?  Laravel如何实现一对一模型关联?(Eloquent示例)  装修招标网站设计制作流程,装修招标流程?  如何在IIS中新建站点并配置端口与IP地址?  node.js报错:Cannot find module &#39;ejs&#39;的解决办法  Win11摄像头无法使用怎么办_Win11相机隐私权限开启教程【详解】  什么是JavaScript解构赋值_解构赋值有哪些实用技巧  Laravel怎么实现API接口鉴权_Laravel Sanctum令牌生成与请求验证【教程】  如何在云虚拟主机上快速搭建个人网站?  Python面向对象测试方法_mock解析【教程】  Laravel如何使用Laravel Vite编译前端_Laravel10以上版本前端静态资源管理【教程】  Swift中循环语句中的转移语句 break 和 continue  如何登录建站主机?访问步骤全解析  Laravel如何使用Blade模板引擎?(完整语法和示例)  Laravel怎么使用artisan命令缓存配置和视图  linux写shell需要注意的问题(必看)  ChatGPT回答中断怎么办 引导AI继续输出完整内容的方法  佐糖AI抠图怎样调整抠图精度_佐糖AI精度调整与放大细化操作【攻略】  利用python获取某年中每个月的第一天和最后一天  Laravel怎么做缓存_Laravel Cache系统提升应用速度的策略与技巧  悟空识字怎么关闭自动续费_悟空识字取消会员自动扣费步骤  Laravel如何实现邮箱地址验证功能_Laravel邮件验证流程与配置  企业网站制作这些问题要关注  如何在阿里云虚拟服务器快速搭建网站?  如何用PHP工具快速搭建高效网站?  北京网站制作公司哪家好一点,北京租房网站有哪些?  网站制作价目表怎么做,珍爱网婚介费用多少?  Laravel如何配置任务调度?(Cron Job示例)  php嵌入式断网后怎么恢复_php检测网络重连并恢复硬件控制【操作】  如何选择PHP开源工具快速搭建网站?  如何快速上传建站程序避免常见错误?  如何快速查询网站的真实建站时间?  Laravel Seeder怎么填充数据_Laravel数据库填充器的使用方法与技巧  企业在线网站设计制作流程,想建设一个属于自己的企业网站,该如何去做?  Laravel怎么配置自定义表前缀_Laravel数据库迁移与Eloquent表名映射【步骤】  Laravel怎么实现微信登录_Laravel Socialite第三方登录集成  如何在宝塔面板中创建新站点?  如何在搬瓦工VPS快速搭建网站?  香港服务器租用费用高吗?如何避免常见误区?  微信小程序 五星评分(包括半颗星评分)实例代码  微信小程序 HTTPS报错整理常见问题及解决方案  Linux系统运维自动化项目教程_Ansible批量管理实战  javascript和jQuery中的AJAX技术详解【包含AJAX各种跨域技术】