Go使用三色标记法进行垃圾回收,将对象分为三种颜色:

颜色定义

  • 白色:未访问的对象(可能被回收)
  • 灰色:已访问但未扫描其引用的对象
  • 黑色:已访问且已扫描其引用的对象(存活对象)

标记过程

// 1. 初始状态:所有对象都是白色
// 2. 从根对象(栈、全局变量)开始标记
// 3. 将根对象标记为灰色
// 4. 扫描灰色对象:
//    - 将其引用的对象标记为灰色
//    - 将自己标记为黑色
// 5. 重复步骤4,直到没有灰色对象
// 6. 白色对象即为垃圾,可以回收

标记示例

type Node struct {
    value int
    next  *Node
}
 
// 假设有以下对象图:
// Root -> A -> B
//      -> C -> D
//      -> E
 
// 标记过程:
// 1. Root标记为灰色:{Root: 灰色, A: 白色, B: 白色, C: 白色, D: 白色, E: 白色}
// 2. 扫描Root,标记A和C为灰色,Root变为黑色:
//    {Root: 黑色, A: 灰色, B: 白色, C: 灰色, D: 白色, E: 白色}
// 3. 扫描A,标记B为灰色,A变为黑色:
//    {Root: 黑色, A: 黑色, B: 灰色, C: 灰色, D: 白色, E: 白色}
// 4. 扫描C,标记D为灰色,C变为黑色:
//    {Root: 黑色, A: 黑色, B: 灰色, C: 黑色, D: 灰色, E: 白色}
// 5. 扫描B,B变为黑色(没有引用):
//    {Root: 黑色, A: 黑色, B: 黑色, C: 黑色, D: 灰色, E: 白色}
// 6. 扫描D,D变为黑色(没有引用):
//    {Root: 黑色, A: 黑色, B: 黑色, C: 黑色, D: 黑色, E: 白色}
// 7. 没有灰色对象,标记完成
// 8. E是白色,可以回收