并发三色标记法
三色:黑、灰、白
- 黑对象代表,对象自身存活,且其指向对象都已标记完成
- 灰对象代表,对象自身存活,但其指向对象还未标记完成
- 白对象代表,对象尙未被标记到,可能是垃圾对象
标记过程:
- 初始化:所有对象都被标记为白色
- 将根对象(全局对象、栈上局部变量等)置黑,将其所指向的对象置灰
- 从灰对象出发,将其所指向的对象都置灰. 所有指向对象都置灰后,当前灰对象置黑
- 标记结束后,白色对象就是不可达的垃圾对象,需要进行清扫
可能产生的问题
- 漏标 ->屏障机制
在某个对象标记为黑色之后,它新指向了一个对象,可能该对象之前被某灰色对象标记,还未扫描到,灰色对象就删除了对该对象的指向
- 多标 ->下一轮GC
在标记完一个灰色对象时,删除了指向它的黑色对象对它的引用
屏障机制
强弱三色不变式
- 强三色不变式:白色对象不能被黑色对象直接引用
- 弱三色不变式:白色对象可以被黑色对象引用,但要从某个灰对象出发仍然可达该白对象
插入写屏障
屏障机制类似于一个回调保护机制,指的是在完成某个特定动作前,会先完成屏障成设置的内容,插入写屏障(Dijkstra)的目标是实现强三色不变式,当一个对象引用另一个对象时,将被引用的对象标记为灰色。
删除写屏障
删除写屏障(Yuasa barrier)的目标是实现弱三色不变式,保证当一个白色对象即将被上游删除引用前,会触发屏障将其置灰,之后再删除上游指向其的引用。
混合写屏障
通过结合这两种写屏障技术,Go 的垃圾回收器可以在并发标记阶段运行,而无需停止整个程序(Stop-the-World)。
插入写屏障和删除写屏障的短板:
- 插入写屏障:结束时需要STW来重新扫描栈,标记栈上引用的白色对象的存活;
- 删除写屏障:回收精度低,GC开始时STW扫描堆栈来记录初始快照,这个过程会保护开始时刻的所有存活对象。
混合写屏障操作:
- GC 开始前,以栈为单位分批扫描,将栈中所有对象置黑
- GC 期间,栈上新创建对象直接置黑
- 堆对象正常启用插入写屏障(添加的对象置为灰色)
- 堆对象正常启用删除写屏障(被删除引用的对象被标记为灰色)
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。