go语言之并发编程入门指南
Go 并发编程指南
一、并发与并行的基本概念
- 并发(Concurrency):多个任务在同一时间段内交替执行(单核或多核皆可)。
- 并行(Parallelism):多个任务在同一时刻同时执行(仅在多核 CPU 中实现)。
二、Goroutine:轻量级线程
1. 基本使用
1 | go func() { |
- 每个
goroutine
约 2KB 栈空间,由 Go 调度器调度(非操作系统线程)。 - 创建开销小,可大规模使用(成千上万)。
2. 注意事项
- goroutine 是异步执行的,主协程退出会导致所有子 goroutine 被杀死。
- 需使用
sync.WaitGroup
或其他手段控制生命周期。
三、通道 Channel:Goroutine 间通信
1. 基本语法
1 | ch := make(chan int) // 创建无缓冲通道 |
2. 特点
- 通道通信是阻塞的(无缓冲时发送/接收都阻塞)。
- 可用于 goroutine 之间安全地共享数据。
3. 关闭通道
1 | close(ch) // 通知接收方不再发送 |
4. 使用 range
读取所有数据
1 | for v := range ch { |
四、select:监听多个通道
1 | select { |
select
会阻塞直到某个分支可执行。- 可用于实现超时、广播、负载均衡等逻辑。
五、WaitGroup:等待一组 goroutine 完成
1 | var wg sync.WaitGroup |
六、Mutex:互斥锁
用于保护共享资源,避免数据竞争。
1 | var mu sync.Mutex |
七、Once:只执行一次(如单例)
1 | var once sync.Once |
八、Cond:条件变量
适用于需要等待某条件成立再继续执行的情况。
1 | var mu sync.Mutex |
九、Context:控制 goroutine 的生命周期
1. 取消 goroutine
1 | ctx, cancel := context.WithCancel(context.Background()) |
2. 超时 / 截止时间
1 | ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) |
十、定时器和 Ticker
1 | time.After(1 * time.Second) // 一次性定时器 |
十一、数据竞争与工具
- 使用
go run -race
启用数据竞争检测。 - Go 的
race detector
是诊断并发程序的强大工具。
十二、高级模式和最佳实践
- 使用工作池(Worker Pool)限制 goroutine 并发数。
- 避免共享内存,推荐通过 Channel 传递数据。
- 对共享状态使用原子操作或互斥锁。
- 理解 CSP 模型:“不要通过共享内存来通信,而应该通过通信来共享内存”。