您的位置:首页 >Golang sync包实现goroutine同步方法
发布于2026-02-08 阅读(0)
扫一扫,手机访问
sync.Mutex 适合保护共享变量,需在访问前 Lock、结束后 Unlock;避免返回带锁字段指针;sync.Once 保证初始化仅一次且不可重置;sync.WaitGroup 要先 Add 再 go,用 defer Done;sync.RWMutex 适用于读多写少场景。

多个 goroutine 同时读写一个 int、map 或结构体字段时,不加锁大概率触发 fatal error: concurrent map writes 或读到脏数据。用 sync.Mutex 最直接:在访问前调用 mu.Lock(),结束后立刻 mu.Unlock()。
常见错误是把带锁的结构体字段以指针形式返回,比如:
func (c *Counter) GetPtr() *int {
c.mu.Lock()
return &c.val // 危险!外部可绕过锁直接改
}
应该改为只返回值,或提供受控的修改方法:
return c.valfunc (c *Counter) Inc() { c.mu.Lock(); defer c.mu.Unlock(); c.val++ }sync.Once 的 Do() 方法适合做单例初始化、配置加载、资源首次创建等场景。它内部用原子操作 + 互斥锁实现,线程安全且开销极小。
注意它不可重置、不可重复使用。一旦 once.Do(f) 执行过,再调用同个 once 实例的 Do() 将直接返回,不管 f 是否 panic(panic 会导致该次调用失败,但标记仍设为已执行)。
sync.Once 变量来“重试”初始化sync.Onceif err := initDB(); err != nil { once.Do(initDB) } —— 这不会重试,因为 once 已标记完成sync.WaitGroup 是等待一组 goroutine 完成的最常用方式。核心是三步:wg.Add(n)、启动 goroutine、每个 goroutine 结尾调用 wg.Done(),主 goroutine 调用 wg.Wait() 阻塞等待。
最容易出错的是调用时机:Add() 必须在 go 语句之前,否则可能 Wait() 已返回而 goroutine 还没被计数;Done() 必须确保执行,哪怕函数 panic,建议用 defer wg.Done()。
go func() { wg.Add(1); ...; wg.Done() }() —— Add 在 goroutine 内,竞态风险高wg.Add(1); go func() { defer wg.Done(); ... }()Add,别靠 len(ch) 之类估算当共享数据读操作远多于写操作(比如配置缓存、路由表),sync.RWMutex 比普通 Mutex 更高效:多个 goroutine 可同时持有读锁,但写锁会独占,且会阻塞新读锁请求(已有读锁不强制释放)。
关键点在于锁粒度和使用习惯:读锁用 RLock()/RUnlock(),写锁仍用 Lock()/Unlock()。混用时注意——写锁必须等所有当前读锁释放后才能获取。
RWMutex 可能比 Mutex 更慢,因读锁维护有额外开销go tool trace 观察 sync 相关阻塞事件,确认是否真因读锁堆积导致延迟
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
正版软件
正版软件
正版软件
正版软件
正版软件
1
2
3
7
9