Go-13-并发深入:sync、context 与连接池
本节目标:掌握 Go 高级并发原语:
sync.Mutex/RWMutex/Once/Pool,context包做超时和取消,以及连接池模式。
1. sync.Mutex(互斥锁)
1 | type Counter struct { |
**互斥锁的”金科玉律”**:
Lock和Unlock必须成对出现- 用
defer Unlock()保证一定会释放 - 不要在持锁时调用可能阻塞的函数(如 I/O、channel 操作)
- 不要在持锁时再次请求同一把锁(死锁)
复制陷阱:sync.Mutex 不能被复制(包含状态):
1 | // 错: |
2. sync.RWMutex(读写锁)
多个读可以并发,写是排他的:
1 | type Cache struct { |
何时用 RWMutex:
- 读多写少(读占比 > 90%)
- 读操作明显比写操作耗时
- 否则用
sync.Mutex即可(RWMutex 自身开销略大)
3. sync.Once(一次性初始化)
保证函数只执行一次,常用于单例模式:
1 | var ( |
Once 的内部实现:
1 | type Once struct { |
4. sync.Pool(对象池)
复用对象,减少 GC 压力:
1 | var bufPool = sync.Pool{ |
Pool 的特性:
- GC 时会被清空(不保证持久)
- 适合短生命周期高频创建的对象(如 bytes.Buffer、临时切片)
- 不适合做连接池(连接需要持久)
5. atomic 包(无锁编程)
1 | import "sync/atomic" |
适用场景:简单的计数器、标志位。
不适用:复合操作(需要事务语义)。
6. context:超时和取消
context 是 Go 的超时和取消机制的标准:
6.1 三种 context
1 | // 根 context |
6.2 传递值
1 | ctx := context.WithValue(context.Background(), "userID", 42) |
注意:
- Value 应该用自定义类型作为 key(避免冲突):
1
2
3type ctxKey int
const userIDKey ctxKey = iota
ctx := context.WithValue(ctx, userIDKey, 42)
6.3 实战:HTTP 请求带超时
1 | func fetch(ctx context.Context, url string) (string, error) { |
6.4 实战:goroutine 链 + 取消传播
1 | func worker(ctx context.Context, id int) { |
7. errgroup:多 goroutine 错误聚合
1 | import "golang.org/x/sync/errgroup" |
特性:
- 任意一个 goroutine 报错,其他都立即停止
- 第一个错误被返回
- 内部用
context.WithCancel实现
8. 连接池实战
Go 标准库没有通用连接池,但有现成模式:
1 | type Conn struct { |
生产用:
- HTTP 连接池:
http.Client内部自动管理 - 数据库连接池:
*sql.DB自动管理 - Redis:
github.com/redis/go-redis/v9客户端池 - 通用池:
github.com/jolestar/go-commons-pool或github.com/silenceper/pool
9. 实战:fan-out / fan-in 模式
扇出(多个 worker 并行处理)→ 扇入(合并结果):
1 | func fanOut(in <-chan int, workers int) []<-chan int { |
10. 限流(rate limit)
1 | import "golang.org/x/time/rate" |
令牌桶算法:
rate.Limit(10):每秒 10 个令牌burst=5:桶容量 5(允许短时间突发)Wait(ctx):阻塞直到拿到令牌(带超时)Allow():非阻塞,返回 bool
11. 最佳实践
- 优先用 channel 通信,必要时用 mutex
- 每个公共函数第一个参数是 ctx(如果是可能被取消的)
- goroutine 数量 = CPU 核数 × 2~10(I/O 密集型)
- 永远考虑 goroutine 退出路径
- 用
-race跑测试 - 池化高频短生命周期对象(bytes.Buffer、临时切片)
- 生产用 errgroup 替代裸 WaitGroup(带 ctx 取消)
小结
| 同步原语 | 用途 |
|---|---|
sync.Mutex |
互斥 |
sync.RWMutex |
读多写少 |
sync.Once |
一次性初始化 |
sync.Pool |
对象复用 |
atomic |
简单原子操作 |
context |
超时/取消/传值 |
errgroup |
多 goroutine 错误聚合 |
rate.Limiter |
限流 |
下一节讲反射(reflect)和元数据编程。
- 本文作者: CoderSong
- 本文链接: https://jack-song-gif.github.io/2026/08/20/Go-13-并发深入:sync与context/
- 版权声明: 本博客所有文章除特别声明外,均采用 MIT 许可协议。转载请注明出处!