p-》lock的传递性
这是本章最反直觉的设计:锁的获取和释放跨越了线程边界。
危机场景
- 进程 A 在
yield()中将状态设为RUNNABLE。 - 进程 A 准备调用
swtch,但还没切走(还在 A 的栈上)。 - 如果此时没有锁: 另一个 CPU 的调度器看到了 A 是
RUNNABLE,决定运行 A。 - 灾难: 两个 CPU 同时运行进程 A(同一个栈)。栈崩溃,数据错乱。
解决方案
- A 拿锁: A 在
yield()开始时获取p->lock。 - A 带着锁切换: A 调用
swtch时不释放锁。 - Scheduler 运行: 切换到 Scheduler 线程。此时
p->lock依然是被锁住的(尽管 CPU 换了,栈换了)。 - Scheduler 放锁: Scheduler 确认 A 已经彻底切走了,才调用
release(&p->lock)。
总结: A 锁门,Scheduler 拔钥匙。这保证了“A 在切换期间,绝对不会被其他 CPU 选中”。