Go sync包:并发同步原语
掌握Go语言sync包中的Mutex、WaitGroup、Once和Cond,实现安全的并发编程。 · 难度:入门 · +15XP
并发同步:sync包
在Go语言中,goroutine是轻量级线程,但多个goroutine访问共享资源时会产生数据竞态。sync包提供了基本的同步原语,帮助我们安全地协调并发任务。
1. Mutex(互斥锁)
Mutex用于保护临界区,确保同一时间只有一个goroutine能访问共享数据。常用方法:Lock()和Unlock()。
var mu sync.Mutex
var counter int
func increment() {
mu.Lock()
counter++
mu.Unlock()
}
注意:使用defer mu.Unlock()可以避免忘记解锁。
2. WaitGroup(等待组)
WaitGroup用于等待一组goroutine完成。三个核心方法:Add(delta)、Done()、Wait()。
var wg sync.WaitGroup
for i := 0; i < 5; i++ {
wg.Add(1)
go func(id int) {
defer wg.Done()
fmt.Printf("goroutine %d done
", id)
}(i)
}
wg.Wait()3. Once(只执行一次)
Once确保某个函数在并发环境下只被执行一次,常用于单例初始化。
var once sync.Once
var config *Config
func getConfig() *Config {
once.Do(func() {
config = loadConfig()
})
return config
}
4. Cond(条件变量)
Cond用于在多个goroutine间等待或通知事件。常用方法:Wait()、Signal()、Broadcast()。
c := sync.NewCond(&sync.Mutex{})
c.L.Lock()
for !condition {
c.Wait() // 等待通知
}
c.L.Unlock()对比表格
| 原语 | 用途 | 关键方法 |
|---|---|---|
| Mutex | 互斥访问共享资源 | Lock/Unlock |
| WaitGroup | 等待一组goroutine完成 | Add/Done/Wait |
| Once | 确保函数只执行一次 | Do |
| Cond | 条件等待与通知 | Wait/Signal/Broadcast |
练习提示
尝试使用Mutex和WaitGroup实现一个并发安全的计数器,启动10个goroutine各自递增100次,最终输出正确结果。注意检查数据竞态。