go-并发
- goroutine 提供高并发
- Go 的多线程调度和多核利用 可以充分利用并发优势
- Go Scheduler + 多线程 + 多核让这些并发任务有机会真正并行执行
- 流程:
goroutine → Scheduler → OS Thread → CPU Core
goroutine 是 Go 创建的并发任务,但 goroutine 自己不能直接在 CPU 上运行;Go Scheduler 会把 goroutine 调度到 OS 线程,OS 再把线程调度到 CPU 核心执行,利用多核 CPU 实现并发
Go Scheduler调度器
- Go Scheduler(Go 调度器) 可以理解 Go 并发的底层核心
- goroutine可以是非常多并发任务,就需要Go Scheduler调度器
- go调度器管理大量 goroutine,并决定哪个 goroutine 在什么时候执行、通过哪个 OS 线程执行
- Go能轻量处理大量并发任务,主要原因是Scheduler调度器
大量 goroutine 高效调度到 OS 线程上执行,并利用多核 CPU 实现并发与并行
go并发对比nodejs并发
CPU 密集任务: CPU 大量计算任务
- go并发核心:goroutine + Scheduler
- 多个 goroutine 可跑在多个 OS 线程
- 当CPU 密集任务时,go处理起来更快
- Scheduler 调度可以把它们安排到不同 OS 线程:
- 利用多核CPU更好的处理并发任务
- node并发核心:Event Loop 事件循环 + 事件驱动 + 非阻塞 I/O
- JS 默认主要跑在一个主线程
- 当任务进行数据库、网络等 I/O 操作时,不需要主线程一直等待
- Event Loop 事件循环可以继续处理其他任务
- node能够快速处理大量 I/O 任务
- 当CPU 密集任务时,容易阻塞主线程
- Node并发主要问题是CPU 密集任务不适合
- 长时间占用 CPU 的同步计算
- 会阻塞 Event Loop
- JS 默认主要跑在一个主线程
并发和并行
并发不等于并行,这个是特别容易以为一样
- 并发 = 多个任务在同一个时间段交替执行,不要求同一个时刻执行
- 并行 = 多个任务在同一时刻执行
并发流程
goroutine → channel → 阻塞 → 缓冲 channel → close → select → WaitGroup → Mutex
Go 并发
│
├── goroutine
│ └── 谁来执行任务
│
├── channel
│ └── goroutine 怎么通信
│
├── select
│ └── 怎么同时处理多个通信事件
│
├── WaitGroup
│ └── 怎么等待多个任务完成
│
├── Mutex / RWMutex
│ └── 怎么保护共享数据
│
└── context
└── 怎么取消、超时、控制任务生命周期
并发循环问题
goroutine
goroutine是 Go 里一种并发执行单元- go自己管理的轻量级线程
- 用于创建并发任务
- 通过go关键字来启动一个goroutine
func task() {
fmt.Println("执行任务")
}
func main() {
go task()
}
WaitGroup
- 用于等待多个 goroutine 任务执行完成
var wg sync.WaitGroup
// 记录需要等待多少任务
wg.Add(2)
go func() {
defer wg.Done() // 任务完成
fmt.Println("任务1")
}()
go func() {
defer wg.Done()
fmt.Println("任务2")
}()
wg.Wait()
channel
- 用于goroutine 之间传数据
channel 阻塞机制
- 控制 goroutine 等待