Go sync包:并发安全与同步原语
学习使用sync包中的Mutex、WaitGroup、Once等原语实现并发安全与协程同步。 · 难度:入门 · +15XP
并发安全与sync包
Go语言通过goroutine实现轻量级并发,但多个goroutine同时访问共享资源时会导致数据竞争。sync包提供了基本的同步原语来保证并发安全。
1. Mutex(互斥锁)
Mutex用于保护临界区,确保同一时间只有一个goroutine访问共享数据。
var mu sync.Mutex
var count int
func increment() {
mu.Lock()
count++
mu.Unlock()
}
// 推荐使用 defer 确保解锁
func safeIncrement() {
mu.Lock()
defer mu.Unlock()
count++
}
2. RWMutex(读写锁)
读多写少场景下,RWMutex允许多个读操作并行,写操作独占。
| 方法 | 行为 |
|---|---|
| RLock() / RUnlock() | 读锁,可被多个goroutine同时持有 |
| Lock() / Unlock() | 写锁,唯一持有,阻塞所有读写 |
3. WaitGroup(等待组)
用于等待一组goroutine完成。主goroutine调用Add设置计数,每个子goroutine完成后调用Done。
var wg sync.WaitGroup
for i := 0; i < 5; i++ {
wg.Add(1)
go func(id int) {
defer wg.Done()
fmt.Printf("Worker %d done
", id)
}(i)
}
wg.Wait() // 等待所有worker完成
fmt.Println("All done")4. Once(只执行一次)
保证某个函数在程序生命周期内只执行一次,常用于单例模式或初始化。
var once sync.Once
var instance *Config
func GetConfig() *Config {
once.Do(func() {
instance = loadConfig() // 只执行一次
})
return instance
}
5. 练习提示
修改下方代码:使用Mutex保护counter变量,启动10个goroutine各递增1000次,最终输出应为10000。注意不要忘记sync导入。