GO语言的垃圾回收是怎么实现的?有哪些流程?随着版本迭代都有哪些优化?
GO语言的垃圾回收是怎么实现的?有哪些流程?随着版本迭代都有哪些优化?
提示
题眼: 标记清除、STW。第六、七题常常合并作答。
Go 的垃圾回收器本质上是基于标记清除思想实现的并发 GC,核心是三色标记加并发清扫。
整体流程可以概括为:
- 从根对象出发进行可达性分析。
- 标记存活对象。
- 清理不可达对象。
- 尽量把标记和清理与用户代码并发执行,减少 STW 时间。
Go GC 的版本演进可以简单记成:
- Go 1.3 之前:几乎全程 STW,卡顿很明显。
- Go 1.3:把标记和清扫拆开,开始减少 STW。
- Go 1.5:引入三色标记,让标记过程更加渐进。
- Go 1.8:引入混合写屏障,进一步提升并发标记的正确性和效率。
写屏障的意义在于:标记阶段用户代码还在运行,对象引用关系还在变化,如果没有额外保护,就可能把本来还活着的对象错当成垃圾回收掉。

重要
参考答案:
Go 的 GC 本质上还是标记清除算法,只不过它在这个基础上做了很多并发优化。传统标记清除会先找出所有存活对象,再把剩下的垃圾清掉,问题在于这个过程如果全都停下来做,STW 时间会比较长。
Go 后面的演进方向基本都围绕一件事,就是尽量减少 STW。早期版本问题比较明显,1.3 开始把清扫并发化,1.5 之后引入三色标记,把标记过程拆得更细,1.8 再通过混合写屏障解决并发标记阶段引用变更的问题。
所以面试里可以概括成一句话:Go 的 GC 是基于三色标记的并发标记清除,核心目标就是在保证正确性的前提下尽量缩短 STW。
