📄 一句话概括
撤下按依赖的逆序发起(C → B → A),但每件不必等前一件收尾——顺序保证的是【不先撤被依赖的】,不是【排队干等】。
📝 本节和前面几节的关系
5.5.1 有了账本,这一节讲照账清理时的一个易混点——顺序到底保证什么、不保证什么。
一、逆序的依据
装的顺序 A → B → C(A 先装,C 依赖 A),撤的时候逆序发起:C → B → A。
为什么逆序?不能先撤别人还依赖的——A 要是先走,B、C 立刻悬空。
逆序是账本算出来的:谁被依赖,谁就最后走。
二、易混点:发起 ≠ 完成
逆序清理说的是【开始清理的顺序】,不是【每件都等前一件清完】。
- C 开始清理后,B 可以同时开始——只要 C 不是 B 的依赖。
- 各件谁先收尾,交给各自的清理耗时。
换句话说:顺序约束的是【谁不能比谁先开始】,不是【谁必须等谁结束】。
三、算一笔账:串行 vs 并行发起
三件插件清理,各需 3、2、1 秒:
- 串行等前一件完成:3 + 2 + 1 = 6 秒。
- 逆序发起、各自完成:max(3, 2, 1) = 3 秒。
差一倍。但重点不是快——是语义: 并发清理不影响正确性(互不依赖),而强制串行会让人误以为【顺序即因果】。
四、什么时候必须等
有一类例外:A 的清理依赖 B 先清完(比如 B 持着 A 要释放的句柄)。
这时账本上的依赖关系会说清:B 的清理必须先完成。
所以规则是:默认并行发起,依赖处显式等待——等待不是猜的,是账上写的。
五、动手 Demo:逆序清理 ≠ 逆序完成
发起顺序与完成时间,两笔账:
cost = {"A": 3, "B": 2, "C": 1}
order = ["C", "B", "A"]
print(" 逆序发起:", " -> ".join(order))
serial = sum(cost.values())
parallel = max(cost.values())
print(" 串行等前一件完成: %d 秒" % serial)
print(" 并行发起各自完成: %d 秒" % parallel)
print()
print(" 顺序约束的是【谁不能先开始】,")
print(" 不是【谁必须等谁结束】")
实跑输出:
--------------------------------------------------------------------
逆序清理 ≠ 逆序完成
--------------------------------------------------------------------
装的顺序是 A -> B -> C,撤的时候按 C -> B -> A **发起**——
这是【逆序清理】。但它不等于【每一件都等前一件清完】。
算一笔账:三件插件清理,各需 3、2、1 秒——
串行等前一件完成 3 + 2 + 1 = 6 秒
逆序发起、各自完成 max(3, 2, 1) = 3 秒
差在一倍。但快不是重点,重点是语义:
说法 含义
----------------------------------------------------------
逆序清理 按依赖的逆序【发起】,保证不先撤别人还依赖的
逆序完成 每件都串行等前一件收尾——没有这个要求
----------------------------------------------------------
换句话说:**顺序保证的是【不先撤被依赖的】,不是【排队干等】。**
逆序的依据在账本:谁被依赖谁最后走——不是习惯,是依赖图。 默认并行发起、依赖处显式等待——等待是账上写的,不是猜的。 这一节纠正的误解很常见:把【逆序】脑补成【串行】。
30 秒实验
- 画出 A → B → C 的依赖图,标出撤下时的发起顺序。
- 举一个【必须显式等待】的清理场景。
- 用一句话向同事解释【逆序清理 ≠ 逆序完成】。
常见误区
- 错误:逆序清理就是一件等一件地撤。——纠正:逆序约束发起顺序,各件收尾互不等待(除非有依赖)。
- 错误:清理顺序可以随便,反正都要撤。——纠正:先撤被依赖的会制造悬空——顺序是依赖图决定的。
- 错误:并行清理不安全。——纠正:互不依赖就可以并行;有依赖处按账显式等待。
自测三问(点开对答案)
1. 撤下为什么按逆序发起? —— **不能先撤别人还依赖的**——A 先走,B、C 立刻悬空。 2. 逆序清理保证什么、不保证什么? —— 保证【谁不能比谁先开始】;不保证【每件等前一件结束】。 3. 什么时候清理必须等待? —— **依赖处显式等待**(如 B 持着 A 要释放的资源)——由账本写明,不是猜的。- ☐ 下一节(5.6 Cordis 的 HMR 建立在生命周期之上)
相关笔记
- Fiber:记录插件实例的一段生命周期 —— 发起顺序就是账算出来的
- Tool Execution Pipeline:一次工具调用究竟要经历哪些阶段 —— 挂载期的依赖检查是前置
- 重构-在不改变程序行为的前提下整理代码 —— 都是【不改变外部行为的前提下动内部】
- 🐳 DeepSeek Harness · 索引