跳到主要内容

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

并发和并行​

并发不等于并行,这个是特别容易以为一样

  • 并发 = 多个任务在同一个时间段交替执行,不要求同一个时刻执行
  • 并行 = 多个任务在同一时刻执行

并发流程​

  • goroutine → channel → 阻塞 → 缓冲 channel → close → select → WaitGroup → Mutex
text
Go 并发
│
├── goroutine
│ └── 谁来执行任务
│
├── channel
│ └── goroutine 怎么通信
│
├── select
│ └── 怎么同时处理多个通信事件
│
├── WaitGroup
│ └── 怎么等待多个任务完成
│
├── Mutex / RWMutex
│ └── 怎么保护共享数据
│
└── context
└── 怎么取消、超时、控制任务生命周期

并发循环问题​

goroutine​

  • goroutine 是 Go 里一种并发执行单元
  • go自己管理的轻量级线程
  • 用于创建并发任务
  • 通过go关键字来启动一个goroutine
go
func task() {
fmt.Println("执行任务")
}

func main() {
go task()
}

WaitGroup​

  • 用于等待多个 goroutine 任务执行完成
go
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 等待