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所示的例子来说明三色标记算法。三色标记算法的原则就是把堆中的对象分配到不同颜色的集合当中,而颜色(黑、白、灰)是根据算法标记的。
首先来解释一下各个颜色代表的含义。
▪黑色集合:没有任何指针指向白色集合的对象集合。
▪白色集合:允许有指针指向黑色集合。
▪灰色集合:可能会有指针指向白色集合的对象。
根据上面的定义可知,白色集合就是最后要回收的对象集合。下面根据该图来介绍一下算法的步骤。
第一步,所有对象进入白色集合,这时三个集合的状态如下。
白色集合: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上搜索查看更多新想法。