GO1.3标记清除,整体需要STW:
1.暂停,找到可达和不可达对象,2. 标记可达对象,3. 清除未标记对象,4. 结束暂停
GO1.5三色标记法,堆启动写屏障,栈不启动,全部扫描一次后,需要重新扫描栈(STW),效率低
如果没有STW,对象丢失的2个条件:
- 黑色对象指向白色对象(白色挂在黑色下面)
- 灰色对象与其可达白色对象之间遭到破坏(灰色也丢失了该白色)
屏障机制,保障对象不丢失的2种方式:
- 强三色不变式:不允许黑色对象指向白色对象
- 弱三色不变式:允许黑色对象指向白色对象,但是该白色对象要被灰色对象可达
为此,go初步得到两种屏障方式:
- 插入写屏障:只使用在堆中,将黑色指向的白色对象标记为灰色;栈要启动STW重新三色标记扫描(仍然需要STW重新扫描栈)
- 删除写屏障:被删除的白色节点标记为灰色(保护灰色对象到白色对象的路径不会断),所以最后一个指向它的指针也依旧可以活过这一轮,在下一轮GC中被清理掉(回收精度低,开始时STW记录初始快照)
为什么在栈中不使用:
GO1.8三色标记法,混合写屏障,栈不启动,堆启动,几乎不需要STW,效率高
结合得到混合写屏障(满足弱三色不变):
- 开始时将所有栈上的可达节点标记为黑色,在GC期间栈上新增的也标记为黑色(无需STW)
- 删除和新增的全部标记为灰色
参考资料: