Go 的 GC 是并发三色标记清除算法。对象分三色:白色(未访问,待回收)、灰色(已发现但引用未扫完)、黑色(已扫完)。标记从根对象(栈、全局变量、寄存器)开始,把根染灰,然后不断从灰对象取出、扫描其引用、把新发现的白色对象染灰、自身染黑,直到没有灰色对象,剩余的白色对象即为垃圾被清扫回收。
并发标记期间用户代码(mutator)仍在修改引用图,可能出现'黑色对象指向白色对象'导致误杀活对象。Go 用混合写屏障解决:Dijkstra 插入写屏障(新引用的对象染灰)加 Yuasa 删除写屏障(被覆盖的旧引用染灰),保证强三色或弱三色不变式。Go 1.8 起 STW(stop the world)时间压缩到亚毫秒级,只在标记开始和结束时短暂停顿;标记和清扫都与用户代码并发执行。
// 观测 GC:
// GODEBUG=gctrace=1 ./app
// 或读 runtime.ReadMemStats / debug.ReadGCStats
追问方向:混合写屏障为什么能去掉 re-scan 栈(Go 1.8 的关键优化)、GC 的 pacing 算法、并发清扫与分配器的配合。