Go微服务实战
上QQ阅读APP看书,第一时间看更新

1.5 垃圾回收

Go语言的垃圾回收也是自动实现的,本节将介绍Go语言的垃圾自动回收功能。所谓垃圾回收,就是释放那些不会再使用的程序所占的空间,比如已经没有引用的变量。垃圾回收过程是与Go程序并发执行的。

很多语言都有垃圾回收机制,比如Java、Python等。对应的垃圾回收策略也有不同,比较著名的垃圾回收机制有引用计数(Reference Counting)、分代收集(Generation)、标记-清除(Mark and Sweep)。

而Go语言的垃圾回收机制是三色标记算法,该算法在论文On-the-fly Garbage Collection: An Exercise in Cooperation内提出,Go团队根据该论文在Go语言中实现了垃圾回收机制,如图1-1所示。

图1-1 Go语言垃圾回收示意图

下面以图1-1所示的例子来说明三色标记算法。三色标记算法的原则就是把堆中的对象分配到不同颜色的集合当中,而颜色(黑、白、灰)是根据算法标记的。

首先来解释一下各个颜色代表的含义。

▪黑色集合:没有任何指针指向白色集合的对象集合。

▪白色集合:允许有指针指向黑色集合。

▪灰色集合:可能会有指针指向白色集合的对象。

根据上面的定义可知,白色集合就是最后要回收的对象集合。下面根据该图来介绍一下算法的步骤。

第一步,所有对象进入白色集合,这时三个集合的状态如下。

白色集合:A B C D E F G H

黑色集合:

灰色集合:

第二步,找到根对象(根对象是指程序能直接访问的对象,比如全局变量),放入灰色集合,此步骤结束后状态如下。

白色集合:B C D F G H

黑色集合:

灰色集合:A E

第三步,取出灰色集合的对象,把这些对象指向的对象取出放入灰色集合,自己则放入黑色集合。如此循环,直到灰色集合为空。此步骤之后状态如下。

白色集合:F G H

黑色集合:A E B C D

灰色集合:

第四步,清理白色集合。

Go语言的垃圾回收是并行处理的,所以在不同集合之间移动的时候要考虑读写问题。Go语言的垃圾回收是通过修改器(Mutator)和写阻塞(Write Barrier)来完成的。

Go语言的垃圾回收机制一直在优化,读者如果对这部分内容感兴趣,可以在GitHub上搜索查看更多新想法。