Skip to content

垃圾回收

  • GC:Garbage Collection,垃圾回收。

一些名词

垃圾内存

  • 程序中不再被引用的对象(即 “垃圾”),释放其占用的内存,供新对象使用。

内存泄漏

  • 程序在分配了内存但不再需要使用时,却未能正确释放这块内存空间,导致这部分内存被占用且无法再次使用,从而造成系统内存的浪费和性能下降。 这种问题会随着程序运行积累,最终可能导致程序甚至整个系统崩溃。

内存溢出

  • 程序在申请内存时,无法满足当前需求,导致内存分配失败。

三色标记法

go gc主要算法是三色标记法(Tri-color Marking),通过将对象分为三种颜色来跟踪其状态:

  • 白色:未扫描的对象(最终会回收)
  • 灰色:已扫描但其引用的对象未扫描(处理中)
  • 黑色:已扫描且其引用的对象均已扫描(存活)

GC 的原理

标记准备(STW,微秒级)

  • 全局 STW,所有用户 G 停止运行,防止内存对象状态突变。
  • 扫描所有根对象,将直接可达的对象标记为灰色,加入 “灰色队列”(待处理队列)。
  • STW 结束,恢复所有业务 P/M/G 运行。
  • 目的: 初始化标记环境、产出第一批灰色对象。

并发标记

  • GC 协程 和 业务协程同时运行
  • 从灰色队列中取出一个灰色对象,将其标记为黑色。
  • 遍历该黑色对象引用的所有子对象:
    • 如果子对象是白色,将其标记为灰色,并加入灰色队列。
    • 如果子对象是灰色,忽略。
    • 如果子对象是黑色,忽略。
    • 循环直到灰色队列为空(初步标记完成)。理论可以全部标记为黑色。

标记终止(STW)

并发标记灰色队列为空后,进入该阶段。

  • 暂停所有业务协程。
  • 并发阶段栈上指针可能被业务代码修改,必须重新扫描根,补全遗漏标记。
  • 处理残留灰色对象,彻底遍历,保证所有存活对象全部标黑。
  • 关闭写屏障。
  • 统计标记结果:区分存活对象(黑)、死亡对象(白)。
  • STW 结束,恢复业务。
  • 收尾标记,保证 100% 标记准确,杜绝并发期间的标记遗漏。

并发清扫

标记完成后,开始回收死亡对象,全程并发。

  • 逐个判断对象颜色:
    • 黑色:存活,保留,颜色暂时不变
    • 白色:已死亡,回收内存,将内存放回堆空闲链表

并发重置

清扫完成后执行,为下一轮 GC 重置状态。

  • 把本轮标记为黑色的存活对象,全部重新置为白色。
  • 清空灰色队列、标记相关状态、计数器。
  • 重置 GC 阈值、辅助 GC 标记状态。
  • 本轮 GC 正式结束,等待下一次内存阈值触发。