Go 三色标记法 · 垃圾回收

Tricolor Mark & Sweep — 用可视化交互讲清楚 GC 到底怎么干活

🔧 初始状态:所有对象标记为白色(待扫描)
白色 White尚未访问(垃圾候选)
灰色 Grey已访问,子对象未扫
黑色 Black已访问且子对象已扫
根对象 Roots栈/全局变量(起点)
步骤 0 / 12

🛡️ 写屏障 (Write Barrier) 演示

在并发标记期间,Mutator(你的业务代码)可能修改对象引用。 比如把 B.next = D 改成 B.next = E,而此时 B 已经变黑了(不会再扫), 如果没有写屏障,E 就会被漏标,导致活对象被错误回收 💀。

Golang 使用 Dijkstra 写屏障:当黑色对象写入新引用时,自动把被引用对象染灰。

💡 核心思想

三色标记法把对象分成 白、灰、黑 三组。从根对象出发,用 BFS 方式遍历引用图, 标记过程结束后,仍然白色的对象就是垃圾,可以回收。 整个过程可以和用户代码并发执行,只短暂 STW。

📋 GC 四个阶段

① Mark Setup — STW,开启写屏障
② Marking — 并发标记,找到所有可达对象
③ Mark Termination — STW,关闭写屏障
④ Sweep — 并发清扫,回收白色对象内存

🤔 为什么用三色?

传统的"标记-清除"需要长时间 STW,程序完全停顿。
三色标记 + 写屏障让 GC 可以和 Mutator 并发工作, 这是 Go 低延迟 GC 的关键设计(目标 < 1ms STW)。