129 / 163 · C11 · 约 8 分钟
关于并发的对话
教授与学生通过多人争抢桌上桃子的日常场景引入并发思想,指出无协调的同时抓取会造成冲突,而排队虽能保证人人有份却牺牲了速度。理想方案必须同时满足正确与高效。随后将类比映射到多线程程序:线程如同独立行动者,共享内存位置就像那些桃子,必须加以协调。操作系统课程关注此主题,是因为内核既要向应用提供锁等同步原语,其自身作为最早的并发程序也必须极其小心地管理内部数据。
桃子场景揭示的并发困境
设想一张堆满桃子的桌子,周围站着许多想吃桃子的人。若每人先用眼睛锁定一颗再伸手去抓,两人很可能同时看中同一颗,后到者只能空手而归。这正是缺乏协调的并发访问所带来的失败。改成排队领取可以保证每人都能拿到桃子,却让所有人依次等待,整体速度大幅下降。真正需要的是一种既能并行又能避免冲突的办法。
线程、共享内存与协调需求
在计算机里,多线程程序中的每个线程就像刚才那些独立行动的人,它们代表同一个程序同时做不同的事情。线程所读写的每一个内存单元,就相当于桌上的一颗桃子。一旦多个线程同时碰到同一块内存却没有任何协调,程序就会出现数据互相覆盖、读到半更新值等莫名其妙的结果。因此必须设计出既允许并行又保证互斥的访问规则。
为何操作系统课必须讨论并发
操作系统课程把并发作为核心支柱,原因有二。第一,内核必须向用户程序提供锁、条件变量等同步原语,让多线程应用能够安全地共享数据。第二,操作系统自身就是历史上第一个真正的并发程序,它同时服务许多进程和中断,内部的各种共享结构一旦访问不当就会立刻导致系统崩溃或数据损坏,因此内核从诞生之日起就必须极其谨慎地编写并发代码。
常见误区
- 线程之间对共享内存不加同步就会产生竞争条件,结果变得完全不可预测。
- 把所有访问都改成严格串行虽然正确,却会彻底丢掉并行带来的性能收益。
- 误以为只有应用程序才需要考虑并发,而忽略内核自身同样充满并发访问。
运行一个例子
这一章用官方 PDF 讲清概念;本页不附带可运行程序。
CHECK YOUR UNDERSTANDING
合上答案,试着解释。
用桃子类比说明:为什么单纯排队既正确又缓慢?这给并发程序设计带来什么启示?
查看参考答案
排队保证同一时刻只有一个人伸手,因此绝不会两人抢同一颗桃子,结果正确;但它禁止任何并行抓取,所以整体很慢。启示是:并发程序需要一种“必要时才互斥、其余时间尽量并行”的机制,才能同时获得正确性与速度。
继续查证
标准草案与官方章节会更新;版本标记只说明示例最低要求。