并发三色标记法

STW的情况下,传统的递归标记算法肯定是没问题的。
但是对实时性高的程序来说,不能接受长时间的STW。
因此,需要对传统的递归标记做改进。通常是实现三色标记法或其改版算法。

三色标记法

三色标记法把对象分成黑白灰。黑色对象认为是计算过的活跃对象,不会被清理。
灰色对象认为是活跃对象,即将被标记成黑色。
白色对象是潜在的垃圾。标记结束后的白色对象会被清理。

流程

初始标记:STW,把GC ROOTS(所谓的GC ROOTS其实就是非堆区引用)直接指向的对象标记成灰色。打开写屏障(删除写或插入写)。 此阶段之后创建的对象堆上对象会变成黑色,防止重复扫描。

并发标记:垃圾收集线程和普通线程一起工作。垃圾收集线程开始标记对象。具体地,每次从灰色对象集取一个灰色对象变成黑色,并将其直接相连的对象变成灰色,加入灰色对象集。这里可以加入老的对象集,也可以加入一个全新的对象集,放到重新标记阶段处理。

重新标记:STW,关闭写屏障。如果有没处理完的对象,重新扫描进行处理。

垃圾回收:释放内存。

写屏障

读屏障和写屏障是处理内存重排序用的。在垃圾收集语境下,写屏障指的是在写操作过程中触发钩子函数。根据钩子函数不同,我们把写屏障简单的分为删除写屏障和插入写屏障。这两种写屏障都是为了满足三色不变性。

三色不变性

强三色不变性:黑色只能连黑色或灰色,不能连白色。
弱三色不变性:黑色可以连白色,但是这个白色要有其他灰色与其直接或间接相连。间接相连的话,路径上是白色。

屏障实现三色不变性

屏障不帮助三色标记法处理多标的情况,只处理漏标。

所谓漏标是:灰色对象指向某个白色对象,但是后来不再指向了。此时有一个黑色对象指向白色对象。因为黑色对象已经计算过了,所以不会再处理。灰色对象也不连接这个白色对象了。这种情况下会发生漏标,发生错误的释放。

分析上述场景可知,涉及两个写操作。即灰色对象删除引用,黑色对象增加引用。

删除写屏障在删除引用时触发,增加写屏障在增加引用时触发。处理方案都是一样的,把被影响的对象标记为灰色。


版权声明:本文为Ning862217083原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
THE END
< <上一篇
下一篇>>