最近看了 jyy 2022 版的 OS 课程,目前进度是并发。对于并发部分,jyy 分了六节课,我目前是看了三节课,梳理一下这三节课的思路。
并发:多处理器编程
这节课的主要问题:如何理解多处理系统?
- 多处理器编程:入门
- 多处理器程序 = 状态机 (共享内存;非确定选择线程执行)
- thread.h = create + join
- 多处理器编程:放弃你对 “程序” 的旧理解多处理器编程:放弃你对 “程序” 的旧理解
- 不原子、能乱序、不立即可见
- 来自于编译优化 (处理器也是编译器)
- Ad hoc synchronization considered harmful (OSDI’10)
- 不原子、能乱序、不立即可见
主要理解多处理器程序是在同一时刻只选取一个线程执行,也就是状态机。这里的意义是建立理论框架,将并发程序抽象为状态机,为后续分析奠定基础。
并发:理解并发程序运行
这节课的主要问题:如何理解各种并发程序?
- 并发程序 = 状态机
- 线程共享内存
- 每一步非确定选择线程执行
- 画状态机就对了
- 当然,用工具帮你画 (model checker)
这节课通过引入 Perterson 算法介绍并证明了它的正确性,然后将并发程序的运行状态抽象为状态机,进而引出了画状态机的程序 model checker。这里的意义是介绍并发程序中,非确定性调度导致程序行为复杂,需严格验证。
并发:并发控制-互斥
这节课的主要问题:如何在多处理器系统上实现互斥?
- 软件不够,硬件来凑 (自旋锁)
- 用户不够,内核来凑 (互斥锁)
- 找到你依赖的假设,并大胆地打破它
- Fast/slow paths: 性能优化的重要途径
这节课先引入具体问题:并发读写共享内存(临界区)导致数据竞争。
并提出了解决手段:
- 硬件基础:原子指令(如 x86
LOCK
前缀、RISC-VLR/SC
)。- 硬件基础提供“不可分割”的指令,确保多核环境下操作的原子性。
- 软件实现:自旋锁(Spinlock)、互斥锁(Mutex)、
futex
(快速用户态互斥锁)- 各种锁都有 Fast/slow path,spin 和 mutex 各有优缺点,因此内核的实现是综合二者实现了 futex 作为互斥锁的底层实现:
- 混合模式:
- Fast Path:无竞争时用户态原子操作(≈自旋锁)。
- Slow Path:竞争时内核休眠(≈互斥锁)。
- 优势:平衡性能(无竞争时快)与资源利用率(竞争时省 CPU)
- 混合模式:
- 各种锁都有 Fast/slow path,spin 和 mutex 各有优缺点,因此内核的实现是综合二者实现了 futex 作为互斥锁的底层实现: