第 3 章 · 并发基础三件套:夜班开工
章节摘要:本章正面回答全书的核心问题——Go 如何让"同时干很多活"变得日常。从 CSP 模型的哲学立场讲起,依次掌握 goroutine(派员工)、channel(开窗口)、select(监听多路)、sync 包(签到板与钥匙柜)、context(下班铃)。每节都以可运行的代码与完整案例落地,读完你能搭出生产者消费者、工作池等经典结构,并知道每条语句在运行时里发生了什么。这是全书的正餐,前两章的准备全部在这里兑现。
本章要解决什么问题
一个值班工程师坐在调度台前,手上有几十个待办任务:有的要等外部响应,有的要密集计算,有的随时可能超时。串行处理意味着一个任务卡住、全线瘫痪;开线程又贵又危险。Go 的答案是:把任务变成廉价的 goroutine,让它们通过 channel 传话而不是抢内存,用 select 同时监听多路,用 context 统一吹下班哨。本章六节就是把这套"排班方法论"逐件发到你手上。
学习目标
- 说清并发与并行的区别,以及 CSP"通过通信共享内存"与传统锁式并发的分野。
- 用 go 关键字启动 goroutine,并用 WaitGroup 或 channel 建立可靠的等待关系,不再依赖 sleep。
- 解释无缓冲与有缓冲 channel 的阻塞规则,正确使用 close 与多返回值接收。
- 用 select 实现多路监听、超时退出与非阻塞收发,理解多就绪时的随机选择语义。
- 在"传话为主、锁为辅"的判断框架下,正确使用 Mutex、RWMutex、WaitGroup 与 Once。
- 用 context 传递取消信号与截止时间,让任意深度的调用链都能统一收工。
核心概念速览
金句:不要让 goroutine 之间共享内存去抢,让它们通过窗口传话来协作——排班的艺术是安排交接,不是安排争抢。
子章节导航
- 3.1 并发模型概述:并发与并行、CSP 与共享内存两种世界观,本套教程所有并发写法的哲学出处。
- 3.2 Goroutine:启动、生命周期、主 goroutine 退出规则,以及 GMP 调度架构如何支撑海量员工在岗。
- 3.3 Channel:无缓冲与有缓冲的阻塞表、close 的责任归属、单向窗口在函数签名里的约束力。
- 3.4 Select:多路监听的语法、随机选择、超时与默认分支三大惯用法。
- 3.5 Sync 包:WaitGroup 签到板、Mutex 钥匙柜、RWMutex 读写分流、Once 一次性开关,及其与 channel 的选型关系。
- 3.6 Context:取消树、截止时间、值传递的规矩,以及"每一层都要尊重取消"的传播纪律。
子章节之间的逻辑关系
本章是一条严格的依赖链:先立观念(3.1),学会派活(3.2);任务多了就要通信(3.3);通信路数多了就要裁决(3.4);某些场景通信不便、必须共享状态,于是需要守护工具(3.5);最后,任何一条并发链路都要能体面收场(3.6)。六节合起来正好覆盖并发程序的完整生命周期:启动、通信、裁决、守护、收工。
3.1 观念
|
3.2 派活 ----> 3.3 传话 ----> 3.4 裁决
| |
+------> 3.5 守护(必要时)<----+
|
3.6 收工(人人必需)
本章知识点清单
- 口述并发与并行的差异,并用"单核交错"与"多核同跑"各举一例。
- 写出"启动 N 个 goroutine 并可靠等待全部结束"的两种标准写法:WaitGroup 与退出 channel。
- 背出无缓冲与有缓冲 channel 在收发两侧的阻塞条件表,并解释 close 后接收的第二返回值。
- 用 select 加 time.After 实现单次操作超时,用 default 实现非阻塞探测。
- 判断一段代码该用 channel 还是 Mutex:数据流向清晰传值用 channel,缓存类共享读改写用锁。
- 写出 context.WithTimeout 配合 select 的标准超时模板,并说出取消后子操作应当快速返回。
前置知识与后续延伸
前置:第 2 章的值语义与指针语义(判断什么数据在共享)、第 1 章的 defer 与错误处理(收尾与上报的语法基础)。缺这两块的话,本章代码会出现大量"能跑但不懂"的暗坑。
后续:第 4 章把本章积木组合成生产级模式并处理故障排障;第 5 章综合实战用并发流水线收束全书。本章的每一行示例都建议亲手运行、故意改坏再观察——并发直觉只能从"亲手弄坏"里长出来。
作者与出处
原作者:灏天文库
来源:平台策划编纂
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流