🐳 第五章 Cordis让插件能够动态组合
📄 一句话概括

撤下按依赖的逆序发起(C → B → A),但每件不必等前一件收尾——顺序保证的是【不先撤被依赖的】,不是【排队干等】。

📝 本节和前面几节的关系

5.5.1 有了账本,这一节讲照账清理时的一个易混点——顺序到底保证什么、不保证什么。

一、逆序的依据

装的顺序 A → B → C(A 先装,C 依赖 A),撤的时候逆序发起:C → B → A。

为什么逆序?不能先撤别人还依赖的——A 要是先走,B、C 立刻悬空。

逆序是账本算出来的:谁被依赖,谁就最后走。

二、易混点:发起 ≠ 完成

逆序清理说的是【开始清理的顺序】,不是【每件都等前一件清完】。

换句话说:顺序约束的是【谁不能比谁先开始】,不是【谁必须等谁结束】。

三、算一笔账:串行 vs 并行发起

三件插件清理,各需 3、2、1 秒:

差一倍。但重点不是快——是语义: 并发清理不影响正确性(互不依赖),而强制串行会让人误以为【顺序即因果】。

四、什么时候必须等

有一类例外: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 秒实验

  1. 画出 A → B → C 的依赖图,标出撤下时的发起顺序。
  2. 举一个【必须显式等待】的清理场景。
  3. 用一句话向同事解释【逆序清理 ≠ 逆序完成】。

常见误区

  1. 错误:逆序清理就是一件等一件地撤。——纠正:逆序约束发起顺序,各件收尾互不等待(除非有依赖)。
  2. 错误:清理顺序可以随便,反正都要撤。——纠正:先撤被依赖的会制造悬空——顺序是依赖图决定的。
  3. 错误:并行清理不安全。——纠正:互不依赖就可以并行;有依赖处按账显式等待。
自测三问(点开对答案) 1. 撤下为什么按逆序发起? —— **不能先撤别人还依赖的**——A 先走,B、C 立刻悬空。 2. 逆序清理保证什么、不保证什么? —— 保证【谁不能比谁先开始】;不保证【每件等前一件结束】。 3. 什么时候清理必须等待? —— **依赖处显式等待**(如 B 持着 A 要释放的资源)——由账本写明,不是猜的。

相关笔记