Go Go 中的 GC 演变是怎样的?详解

标记清除法

在 Go v1.3 之前采用的是 标记-清除(mark and sweep)算法。

它的逻辑是,先将整个程序挂起(STW, stop the world),然后遍历程序中的对象,只要是可达的对象,都会被标记保留(红色),而那些不可达的对象(白色),则会被清理掉,清理完成后,会恢复程序。然后不断重复该过程。

这种标记-清除的算法,会有一段 STW 的时间,将整个程序暂停,这对于一些实时性要求比较高的系统是无法接受的。

另外,上面这个标记的过程扫描的是整个堆内存,耗时比较久,最重要的是,它在清除数据的时候,会产生堆内存的碎片。

因此从 Go v1.5 开始,就开始抛弃这种算法,而改用 三色并发标记法

三色并发标记法

新算法的出现,必然是要解决旧算法存在的最关键问题 ,即STW 的暂停挂起导致的程序卡顿。

它的逻辑就是,准备三种颜色,分别对三种对象进行标记:

既然 STW 会挂起程序,那是不是可以考虑将其摘除呢?

摘除会带来一个问题就是在标记的时候,程序的运行会不断改变对象的引用路径,影响标记的准确性。

关于不使用 STW 带来的影响可以看一下这篇文章:https://segmentfault.com/a/1190000022030353

总结来说,就是当在标记的时候出现 :一个白色对象被黑色对象引用,同时该白色对象又被某个灰色(或者上级有灰色对象)对象取消引用的情况,就会标记不准确。

因此如果想摘除 STW,那就得规避掉上面这个场景出现。

解决方法是:使用 插入屏障删除屏障

插入屏障

在A对象引用B对象的时候,B对象被标记为灰色。(将B挂在A下游,B必须被标记为灰色)

删除屏障

被删除的对象,如果自身为灰色或者白色,那么被标记为灰色。

延伸阅读

教程来源于Github,感谢iswbm大佬的无私奉献,致敬!

技术教程推荐

持续交付36讲 -〔王潇俊〕

许式伟的架构课 -〔许式伟〕

深入浅出云计算 -〔何恺铎〕

MySQL 必知必会 -〔朱晓峰〕

容量保障核心技术与实战 -〔吴骏龙〕

程序员的个人财富课 -〔王喆〕

零基础入门Spark -〔吴磊〕

大厂广告产品心法 -〔郭谊〕

结构会议力 -〔李忠秋〕