Go垃圾回收
1. 常见垃圾回收算法对比
垃圾回收(Garbage Collection, GC)是指对程序中不再使用的内存资源进行自动回收的操作。常见的 GC 算法包括:
引用计数(Reference Counting)
- 原理:每个对象维护一个引用计数器,增加引用时 $+1$,引用失效时 $-1$,计数归零时直接回收。
- 优点:回收及时,不会出现内存耗尽或达到阈值才触发的情况。
- 缺点:无法解决循环引用问题,且频繁更新计数有性能开销。
标记-清除(Mark-Sweep)
- 原理:从根对象(GC Roots)开始遍历所有可达对象并标记“被引用”,遍历结束后对未标记的白色对象进行回收。
- 优点:能够有效解决循环引用问题。
- 缺点:需要 Stop The World(STW),短暂停顿所有用户协程/线程。
分代收集(Generational Collection)
- 原理:根据对象的生命周期长短划分为新生代和老年代,不同代采用不同的回收算法和频率。
- 优点:针对不同生命周期的对象优化,整体回收性能优秀。
- 缺点:实现逻辑较为复杂。
2. 三色标记法(Three-color Marking)
Go 语言采用了并发三色标记清除算法。算法将对象分为三种颜色:
- 白色:未被扫描到的对象(潜在的垃圾对象)。
- 灰色:已被扫描到,但其引用的其他对象尚未被完整扫描。
- 黑色:已被扫描到,且其引用的所有对象也都已被扫描(可达的安全对象)。
标记过程:
- 初始状态:所有对象归为白色。
- 根扫描:从根节点(如全局变量、栈上的变量)开始遍历,将直接可达的对象放入灰色集合。
- 对象追踪:遍历灰色集合,将灰色对象引用的对象标记为灰色,然后将该灰色对象自身转为黑色。
- 循环迭代:重复上述步骤,直到灰色集合中没有对象。
- 垃圾清理:此时剩下的白色对象即为不可达垃圾,进行统一回收。
3. STW 与写屏障(Write Barrier)
3.1 为什么需要 STW?
为了防止在 GC 扫描过程中,用户协程修改指针引用关系,导致 GC 误删正在被引用的存活对象。通过 Stop The World (STW) 暂时挂起所有正在运行的 Goroutine,可以保证引用数据的一致性。目前 Go 的 STW 优化已能控制在 1ms 以下。
3.2 对象丢失的两个必要条件
若要完全消除或极大地缩短 STW,引入混合写屏障来解决并发标记期间的引用变更问题。对象被误回收必须同时满足以下条件:
- 黑色对象新增了指向白色对象的引用。
- 该白色对象没有其他灰色对象的直接/间接引用,或者原有的灰色引用被删除了。
3.3 屏障技术实现
屏障技术通过破坏上述两个条件之一来保证三色不变性:
- Dijkstra 插入写屏障(强三色不变性)
- 规则:黑色节点不允许直接引用白色节点。当黑色节点新增白色节点的引用时,强制将该白色节点修改为灰色。
- Yuasa 删除写屏障(弱三色不变性)
- 规则:允许黑色节点引用白色节点,但前提是该白色节点仍有其他灰色节点的间接引用。当白色节点被删除引用时,悲观地将其置为灰色,防止误杀。
- 本文标题:Go垃圾回收
- 创建时间:2026-08-11 16:27:48
- 本文链接:2026/08/11/gogc/
- 版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
评论