标签: Channel

  • Go并发编程精讲:goroutine/channel原理与避坑指南

    Go并发编程精讲:goroutine/channel原理与避坑指南

    深入理解 GMP 调度模型

    Go 运行时调度器将 goroutine 映射到 OS 线程上执行,GMP 代表 G(Goroutine)、M(Machine/OS 线程)、P(Processor,执行上下文)。P 的数量默认等于 CPU 核心数,可以通过 GOMAXPROCS 调整,这是 Go 并发性能的关键参数。

    goroutine 的生命周期与状态

    goroutine 有多个状态:waiting(阻塞在 channel 或系统调用)、runnable(就绪等待调度)、running(正在执行)。理解这些状态有助于分析死锁和性能问题。

    channel 的底层实现

    channel 内部有环形队列和两个等待队列(sendq 和 recvq)。向已满的无缓冲 channel 发送会阻塞,goroutine 被挂在 sendq 上;接收时会从 recvq 唤醒一个 sender 或从队列取数据。

    常见并发陷阱

    • 向已关闭的 channel 发送数据会 panic,但接收会返回零值
    • 多个 goroutine 同时等待同一个 channel,只有 1 个会被唤醒——用 sync.WaitGroup 而非 channel 控制退出
    • for range channel 会一直阻塞直到 channel 关闭
    • context.WithCancel 是优雅退出多个 goroutine 的标准方式

    小结

    理解 GMP 调度和 channel 底层原理,才能真正写出高效的并发代码。遇到性能问题时,用 runtime.NumGoroutine() 和 pprof 分析 goroutine 的状态分布是第一步。

    来源:https://www.dnote.cn