首先,位于栈区的指针不加写屏障,目的是为了保证效率
1.插入屏障:A指向B,将B标记为灰色
目的:保证黑对象永远不会指向白对象(只能是灰、黑)(强三色不变式)
缺点:由于栈指针没有写屏障,栈指针可能会指向白对象,因此标记完需要STW,扫描栈区所有指针重新标记
2.删除屏障:A重新指向别的对象,A标记为灰色;开始时将整个栈置黑,次一级(堆对象)置灰
目的:所有堆对象都在灰色对象的保护之下(弱三色不变式)
缺点:
B可能不会被清除,只能等待下一次gc;
A重新被置为灰,造成冗余扫描(波面回退)
开始时需要STW,扫描所有goroutine栈,对所有根对象置黑,次一级对象置灰(次一级对象其实就是所有堆对象),这样做可以避免根对象持有白色指针,且所有堆对象都在灰色对象的保护下
3.混合屏障
指向者和被指向者都置为灰色,保证了弱三色不变式
注意:同样,栈指针不加写屏障;开始时只对单个协程栈进行扫描并把根对象置黑,次一级(堆对象)置灰,不需要STW。相当于在删除屏障的基础上加上了插入屏障的逻辑(被指向者置灰)
优点:不再需要STW,但需要标记两次
参考:
https://www.jianshu.com/p/6536f951166a
https://www.jianshu.com/p/4c5a303af470