V1.3
标记清除+STW,这个比较好理解,就不详细阐述了。
V1.5
提出了三色标记法,伴随有STW
新生的对象都会标记成白色,然后从根节点出发一次遍历,将遍历过的对象标记成灰色的,并且全局变量和栈中的对象置灰色。
最后将灰色对象标记为黑色,直到没有灰色对象全部转换成黑色对象为止。将所有的白色对象全部回收。
假设没有STW,在标记过程中很有可能出现引用关系的改变。一旦改变了这个关系(尤其是黑色对象直接指向白色对象),就会出现“误删除”的操作。
上述情况只针对于下面两个条件:
- 一个白色对象被黑色对象引用(白色被挂在黑色下)
- 灰色对象与它之间的可达关系的白色对象遭到破坏(灰色同时丢了该白色) 如果当以上两个条件同时满足时,就会出现对象丢失现象!
STW也暴露出很大的性能瓶颈问题,针对上述问题提出了相应的解决方案。
引入了屏障机制
- 强三色不变式 不允许黑色对象引用白色对象
- 弱三色不变式 白色对象存在灰色对象的引用,或者可达它的链路的上游存在灰色对象,黑色对象就可以引用白色对象
插入屏障
在堆上的黑色对象引用白色对象时,需要把白色对象标记成灰色对象,满足强三色不变式
栈上的对象会在STW 的保护下重新进行标记
删除屏障
被删除的对象,本身如果是灰色或者白色都会标记成灰色对象
满足弱三色不变式
V1.8
针对插入写屏障和删除写屏障的短板:
● 插入写屏障:结束时需要STW来重新扫描栈,标记栈上引用的白色对象的存活;
● 删除写屏障:回收精度低,GC开始时STW扫描堆栈来记录初始快照,这个过程会保护开始时刻的所有存活对象。
于是引入了混合写屏障 ,避免了对栈的re-scan操作,极大地减少了STW的时间。
具体操作:
1、GC开始将栈上的对象全部扫描并标记为黑色(之后不再进行第二次重复扫描,无需STW),
2、GC期间,任何在栈上创建的新对象,均为黑色。
3、被删除的对象标记为灰色。
4、被添加的对象标记为灰色。
以上就是对Golang垃圾回收机制中的三色标记的详细描述,希望同学们批评指正。