垃圾回收

1. 三色标记法

go的垃圾回收机制是通过三色标记法来实现的,其中

  • 黑色:没有指向(引用)白色集合中的任何对象
  • 灰色:可能指向(引用)白色集合中的某些对象
  • 白色:剩下的需要被回收的候选对象,当灰色集合为空时,表示白色集合中的对象都没有被引用,那么这些对象就可以被回收。

一个垃圾回收循环的步骤:

  1. 将所有的对象都放入白色集合中
  2. 扫描所有roots对象,放入灰色集合中,roots对象表示在应用中可以被直接访问,一般是全局变量和其他在栈中的对象。
  3. 将灰色集合中的某个对象放入黑色集合,然后扫描这个对象有引到到的白色集合中的对象,将那些白色集合中引用到的所有对象放入灰色集合,以此类推,将灰色集合中的对象不断放入黑色集合中,然后白色集合中的对象不断放入灰色集合中。
  4. 当灰色集合中的对象为0,即都被放入到黑色集合中了,表示没有任何对象会引用到白色集合中的对象了,因为黑色集合存放不会引用白色集合对象的元素,而灰色集合为0,也不存在引用白色集合对象的元素。所以白色集合中的对象即是没有被引用的对象,可以回收的对象。

2. 三色标记和写屏障

这是让标记和⽤户代码并发的基本保障,基本原理:

  • 起初所有对象都是⽩⾊。
  • 扫描找出所有可达对象,标记为灰⾊,放⼊待处理队列。
  • 从队列提取灰⾊对象,将其引⽤对象标记为灰⾊放⼊队列,⾃⾝标记为⿊⾊。
  • 写屏障监视对象内存修改,重新标⾊或放回队列。

当完成全部扫描和标记⼯作后,剩余不是⽩⾊就是⿊⾊,分别代表要待回收和活跃对象,清理操作只需将⽩⾊对象内存收回即可。

3. 标记清除算法 (Mark-Sweep)

标记-清除算法分为两个阶段:标记阶段和清除阶段。

标记阶段的任务是标记出所有需要被回收的对象,清除阶段就是回收被标记的对象所占用的空间。

优点是简单,容易实现。 缺点是容易产生内存碎片,碎片太多可能会导致后续过程中需要为大对象分配空间时无法找到足够的空间而提前触发新的一次垃圾收集动作。(因为没有对不同生命周期的对象采用不同算法,所以碎片多,内存容易满,gc频率高,耗时)

待完善


最后修改 June 11, 2025: update go (0b08187)