一架梯子,一头程序猿,仰望星空!
Golang高级特性面试题 > 内容正文

能简述下Golang的GC原理吗?


问题简答

​ Golang中的垃圾回收主要应用三色标记法,GC过程和其他用户goroutine可并发运行,但需要一定时间的STW(stop the world),STW的过程中,CPU不执行用户代码,全部用于垃圾回收,这个过程的影响很大,Golang进行了多次的迭代优化来解决这个问题。

问题详解:

Golang 1.5版本以后采用三色并发标记法处理垃圾回收。

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

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

  • 黑色:检测到有被引用,并且已经遍历完它所有直接引用的对象或者属性
  • 白色:还没检测到有引用的对象(检测开始前,所有对象都是白色,检测结束后,没有被引用的对象都是白色,会被清查掉)
  • 灰色:检测到有被引用,但是他的属性还没有被遍历完,等遍历完后也会变成黑色

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

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

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

因此如果想摘除 STW,那就得规避掉上面这个场景出现。
解决方法是:使用 插入屏障 和 删除屏障

插入屏障

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

删除屏障

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