前言
判断对象存活主要有两种方式,一种是引用计数方式,另外一种就是可达性分析。go 中判断对象存活采用的是可达性分析,而其 gc 使用的便是三色标记算法。
gc的核心目标
gc的核心目标是系统能够长期稳定地运行,阻碍这一目的的核心限制之一便是机器内存的限制,机器内存不是无尽的,而是有限的,所以需要对程序所申请的内存进行管理。目前通用的内存管理方式有三种:
- 开发者手动分配和回收,类似 c/c++
- 由系统自动分配和回收,类似java/go
- 无 GC,编译时决定对象生命周期,类似 rust 1与2是运行时决定对象的生命周期,3 是编译时就已经决定对象的生命周期,具体参见rust 的所有权
系统长期稳定运行的重要指标是,吞吐和延时。
- 吞吐关注的是单位时间内系统能够处理的任务量。
- 延时关心的是每个任务的响应时间。
我们的目的都是高吞吐和低延时,但是这两个目标有时候是无法两全的。go 更加强调的是它的低延时,其 GC 的低延时也是其引以为豪的一大特性。
下面我们来看一下 Go 的GC 算法,三色标记清除算法。【ps.为什么是三色,而不是二色、四色,其实有点像数学上的四色定理】
三色标记清除算法的主要过程
前置条件,所有的节点都必须是三种颜色之一。
- 回收开始前所有的对象都是白色,例如现在有A、B、C D 4个对象,初始都是白色


-
标记颜色,把A变为黑色,同时A的引用B变为灰色,若B有子引用对象,这一过程会持续下去,直至灰色节点为空
-
此时如果有新的对象生成,如图3节点 E所示,或者是白色对象的引用发生变更,如图3节点D所示

- 在下一轮遍历中,B、D、E节点都会被标记为黑色



小结
官方给出的测试结果显示 go 的 stw 时间很短,毕竟其发生 stw 的阶段只会发生在标记 GC roots 的阶段以及标记完成阶段。但是这并不代表其一定比 jvm 的GC收集器优秀,毕竟jvm可以对吞吐和延时做取舍,选择更合适自己的 GC收集器。