并发和 Goroutine
Go 的并发模型是其最显著的特性之一,围绕 goroutine 和 channel 的概念构建。与 JavaScript 的单线程事件循环或 C++ 的复杂线程模型不同,Go 提供了一种简单而强大的并发编程方法,其座右铭是"不要通过共享内存来通信;要通过通信来共享内存"。
并发 vs 并行
并发是通过交错执行来处理多个任务的能力,而并行是在不同 CPU 核心上同时执行多个任务的能力。
- JavaScript: 主要通过事件循环实现并发,通过 Web Workers 实现有限的并行
- Go: 既支持并发(goroutine)也支持并行(可以利用多个 CPU 核心)
Goroutine: 轻量级线程
Goroutine 是 Go 处理并发操作的方式。它们是由 Go 运行时管理的轻量级线程,而不是操作系统。
正在加载...
Goroutine 生命周期
创建 Goroutine
Goroutine 使用 go
关键字后跟函数调用来创建:
正在加载...
Goroutine 同步
与 JavaScript 基于 Promise 的同步不同,Go 使用 channel 和同步原语:
正在加载...
Channel: Goroutine 间的通信
Channel 是 Go 中 goroutine 间通信的主要机制。它们提供了一种安全的数据共享方式,无需显式锁定。
基本 Channel 操作
正在加载...
缓冲 vs 无缓冲 Channel
正在加载...
Select 语句
select
语句允许 goroutine 等待多个 channel 操作:
正在加载...
常见并发模式
工作池模式
正在加载...
管道模式
正在加载...
Goroutine 最佳实践
1. 始终处理 Goroutine 生命周期
正在加载...
2. 避免 Goroutine 泄漏
正在加载...
性能考虑
Goroutine vs 线程对比
方面 | Goroutine | 操作系统线程 |
---|---|---|
内存 | ~2KB 栈 | ~1MB 栈 |
创建 | ~0.3μs | ~17μs |
上下文切换 | ~0.2μs | ~1.7μs |
并发数 | 百万级 | 千级 |
何时使用 Goroutine
- I/O 密集型操作: 网络请求、文件操作
- CPU 密集型操作: 数学计算(需要适当协调)
- 事件处理: 并发处理多个事件
- 后台任务: 清理、监控、日志记录
练习题:
- Go 中并发和并行有什么区别?
- Goroutine 在资源使用方面与操作系统线程有何不同?
- 解释缓冲 channel 和无缓冲 channel 的区别。
- 什么时候使用
select
语句而不是简单的 channel 接收? - 防止 goroutine 泄漏有哪些常见模式?
项目想法:
创建一个使用 goroutine 并发获取多个 URL 的网络爬虫,包含适当的错误处理和速率限制。爬虫应该使用 channel 来协调工作线程并收集结果。