登录
首页 >  Golang >  Go教程

Golang并发统计技巧:goroutine与原子操作应用

时间:2026-01-18 23:06:43 220浏览 收藏

知识点掌握了,还需要不断练习才能熟练运用。下面golang学习网给大家带来一个Golang开发实战,手把手教大家学习《Golang并发统计技巧:goroutine与原子操作应用》,在实现功能的过程中也带大家重新温习相关知识点,温故而知新,回头看看说不定又有不一样的感悟!

不能直接用普通变量做并发计数,因为count++非原子操作(读-改-写三步),会导致数据竞争;应使用sync/atomic包的原子操作,如atomic.AddInt64和atomic.LoadInt64,且所有读写必须统一走原子操作。

如何使用Golang实现并发数据统计_Golang goroutine与sync原子操作方法

为什么不能直接用普通变量做并发计数

多个 goroutine 同时对一个 int 变量执行 ++,结果大概率比预期小。这不是“偶尔出错”,而是因为 count++ 实际包含三步:读取、加1、写回——中间可能被其他 goroutine 打断。Go 的竞态检测器(go run -race)会立刻报出 Data race 错误。

sync/atomic 是最轻量的正确解法

适用于单个数值的增减、比较交换等简单操作,无锁、零分配、性能接近汇编。注意类型必须严格匹配:int64 不能用 atomic.AddInt32uint32 不能用 atomic.AddUint64

  • 计数器必须声明为 int64(即使你只计到 100),因为 atomicint 没有通用函数,且 int 在 32 位系统上非原子
  • atomic.AddInt64(&counter, 1) 替代 counter++;用 atomic.LoadInt64(&counter) 读值,不要直接读变量
  • 避免混用:一旦用了 atomic,所有读写都必须走原子操作,否则仍存在数据竞争
package main

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

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

    for i := 0; i 

<h3>什么时候该换 sync.Mutex 而不是硬套 atomic</h3>
<p><code>sync/atomic</code> 只能处理单个值的简单操作。一旦统计逻辑变复杂——比如要同时更新计数器和记录最后更新时间、或需要条件重置、或要聚合多个字段(成功数/失败数/平均耗时)——就必须升级到 <code>sync.Mutex</code> 或 <code>sync.RWMutex</code>。</p>
  • 别为了“看起来快”强行拆解逻辑去适配 atomic,可读性和正确性优先
  • 如果读多写少(如高频查询当前统计值,低频更新),用 sync.RWMutex 提升并发读性能
  • Mutex 保护的是临界区代码段,不是某个变量;锁粒度要尽量小,但别细到每行都加锁

map 并发读写必须加锁或换 sync.Map

原生 map 非并发安全。直接在多个 goroutine 里 m[key]++ 会 panic:fatal error: concurrent map writes

  • 若 key 数量可控、读写频率均衡,用 sync.Mutex 包裹 map 操作最直观
  • 若 key 极多、读远多于写、且能接受弱一致性(如统计上报场景),可用 sync.Map,但它不支持遍历和 len(),且内部有额外指针跳转开销
  • 千万别用 map + atomic 混合——atomic 对 map 本身无效,只对指针或整数有用

容易被忽略的一点:哪怕你只读 map,只要其他 goroutine 在写,也必须加锁(或使用 sync.MapLoad 方法)。Go 不保证非同步读的内存可见性。

到这里,我们也就讲完了《Golang并发统计技巧:goroutine与原子操作应用》的内容了。个人认为,基础知识的学习和巩固,是为了更好的将其运用到项目中,欢迎关注golang学习网公众号,带你了解更多关于的知识点!

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