资讯动态

Go atomic

发布时间:2026/8/24 1:03:53 来源:尧图企业网站定制
Go atomic一、介绍atomic是 Go 标准库中用于实现原子操作的包核心解决多 goroutine 并发下的变量竞态问题比互斥锁sync.Mutex更轻量、性能更高。二、原子操作2.1 介绍原子操作是指不可被中断的操作要么完全执行完毕要么完全不执行中间不会被其他goroutine抢占。2.2 底层原理atomic.AddInt32(x, 1)是一步完成的底层依赖CPU 指令如 LOCK XADD通过锁定内存总线/ 缓存行确保同一时刻只有一个CPU核心操作该内存地址保证原子性无竞态风险三、适用场景轻量级的计数eg 请求数、并发数统计状态标记eg 服务是否启动 任务是否完成高性能的并发变量更新替代互斥锁、减少上下文切换四、核心功能atomic 主要操作基本数值类型int32/int64/uint32/uint64/uintptr和指针类型Pointerps atomic 操作的对象是一个地址需要传递地址4.1 Add对数值类型进行原子增减给第一个参数地址中的值增加一个 delta 值变量必须是指针类型因为要直接操作内存uint 类型加法若要实现减法需通过 atomic.AddUint32(x, ^uint32(n-1))利用补码例如 atomic.AddUint32(x, ^uint32(0)) 等价于 x–packagemainimport(fmtsyncsync/atomic)funcmain(){varcountint320// 必须是int32/int64等原子支持的类型varwg sync.WaitGroup// 启动1000个goroutine每个goroutine对count加1fori:0;i1000;i{wg.Add(1)gofunc(){deferwg.Done()// 原子加1第一个参数是变量指针第二个是增量负数表示减atomic.AddInt32(count,1)}()}wg.Wait()fmt.Println(最终计数,count)// 输出 1000无竞态}4.2 加载操作Load原子读取变量值保证读取到的是最新值避免编译器 / CPU 缓存导致的可见性问题4.3 存储操作Store原子写入变量值保证写入的原子性和可见性其他 goroutine 能立即看到最新值替代普通赋值 x 0避免并发下的写覆盖问题packagemainimport(fmtsync/atomictime)varstatusint321funcgetStatus(){fmt.Println(atomic.LoadInt32(status))}funcstop(){atomic.StoreInt32(status,0)}funcmain(){gogetStatus()gostop()time.Sleep(time.Second)}结果可能是1也可能是04.4 比较并交换CASfuncCompareAndSwapInt32(addr*int32,old,newint32)(swappedbool)方法逻辑检查addr指向的变量值是否等于old若相等将其更新为new返回true若不相等不做修改返回false。CAS 是乐观锁思想无阻塞但可能重试Go 中sync/atomic的 CAS 是硬件级别的支持性能远高于互斥锁packagemainimport(fmtsync/atomictime)varstatusint321funcincr(){for{old:atomic.LoadInt32(status)new:old1// CAS操作只有old等于当前值时才更新ifatomic.CompareAndSwapInt32(status,old,new){fmt.Println(status:,atomic.LoadInt32(status))break}}}funcmain(){goincr()time.Sleep(time.Second)}4.5 交换操作Swap无条件原子替换变量值返回旧值eg: 强制重置计数器4.5 atomic.Value支持任意类型的原子读写ps :atomic.Value存储的类型必须固定比如第一次存 map后续不能存 int)存储引用类型如 map、slice时必须拷贝后修改避免并发读写原对象packagemainimport(bytesfmtstrconvsyncsync/atomictime)funcmain(){vardate atomic.Value// 1. 存储数据date.Store(map[string]time.Time{time1:time.Now()})varwg sync.WaitGroupfori:0;i10;i{wg.Add(1)gofunc(){deferwg.Done()// 2. 加载数据oldMap:date.Load().(map[string]time.Time)// 3. 拷贝旧数据避免修改原数据newMap:make(map[string]time.Time)fork,v:rangeoldMap{newMap[k]v}buf:bytes.NewBuffer([]byte{})buf.WriteString(time)buf.WriteString(strconv.Itoa(i))newMap[buf.String()]time.Now()date.Store(newMap)}()}wg.Wait()fmt.Println(len(date.Load().(map[string]time.Time)))fmt.Println(date.Load().(map[string]time.Time))fmt.Println(main done)}五、与mutex比较特性atomicsync.Mutex适用场景单个变量的原子操作 如计数、状态标记复杂逻辑 / 多个变量的原子操作(比如转账扣减 A 账户 增加 B 账户)性能极高硬件指令级较低有上下文切换开销使用复杂度简单仅支持基本操作灵活支持任意逻辑竞态保护仅保护变量读写保护代码块

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价