三色标记算法

本文探讨了CMS垃圾收集器在并发标记期间采用的三色标记法,解释了如何避免漏标问题,并介绍了增量更新策略来追踪引用变化。重点在于理解对象标记过程和漏标的成因及解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

CMS垃圾收集器在并发标记时,使用的算法是三色标记,把对象在逻辑上分成三种颜色,如下图
在这里插入图片描述
如下图,一个对象A,他所引用的对象B是灰色的的,说明B已经被标记了,而A自身也被标记了,所以A就变成黑色的了,就说明它自身和它的成员变量都已被标记完成。B对象里有一个引用指向了白色的对象C,白色是代表没有被标记的对象,所以B就是灰色的,说明它只是自身被标记了,而它的成员变量没有被标记,而C对象就是白色的,说明是没有被标记的,是会被当成垃圾回收的。
在这里插入图片描述

漏标:
漏标是指,本来是存活的对象,但是由于没有被标记到,所以被当成垃圾回收了。

什么情况下产生漏标
如果在并发标记的过程中,可能会发生,B对象指向C对象的引用消失了,而A对象指向了C对象,因为这个时候A是黑色的,代表它自身和成员变量都已被标记完成了,所以下一次扫描的时候,就不会去管这个A对象了,也不会去管这个A里成员变量有没有被标记了,所以这个C是不会被标记到的,这时候这个C对象就被漏标,会被当成垃圾回收了。
在这里插入图片描述
解决方案
CMS使用的是incremental update(增量更新)这个方法,就是跟踪A指向C的引用增加,产生新的引用后,关注引用的增加。
原理就是把A的重新标记为灰色,因为灰色代表自身被标记,而成员变量未被标记,这个时候当下一次扫描的时候,一看这个A是灰色,那就说明它的成员标量没有被标记,就回去找A的成员标量去标记,这个时候就找到C了。

### 三色标记算法的工作原理 在垃圾回收领域,三色标记法作为一种高效的并发垃圾收集技术被广泛应用。此方法通过引入三种不同状态来区分对象的生命期:白色表示尚未访问过的对象;灰色代表正在处理中的对象;黑色则指代已经完成扫描的对象[^2]。 对于基于三色标记的清除过程而言,在初始状态下所有对象均设为白色。当启动一次完整的垃圾回收周期时: - 首先进入**标记阶段**,此时根节点集合里的活跃对象会被染成灰色并加入到待处理队列中。随后程序不断从未处理列表取出一个灰度元素将其变为黑体,并检查其引用的所有子项。如果某个子项当前仍保持默认颜色即白色,则同样变更为灰色并入栈等待进一步探索直到整个图结构内不再含有任何灰色结点为止[^3]。 - 接着转入**清除阶段**,期间仅需简单地释放掉那些依旧维持原初色泽(也就是未曾触及过)的目标实体所占用的空间资源即可实现内存的有效管理[^1]。 值得注意的是,在实际应用过程中由于应用程序线程可能持续创建新实例或修改已有链接关系从而引发所谓的“浮动垃圾”,以及造成重复标注或是遗漏某些应当删除的数据单元等问题。因此为了确保准确性通常还需要额外采取措施解决这些潜在风险[^4]。 ```java // Java伪代码示例展示了如何利用三色标记进行垃圾回收 public class GarbageCollector { public void markAndSweep() { // 初始化所有对象的颜色为白色 initializeObjectsToWhite(); // 将根集中的对象设置为灰色并放入工作列表 for (Object root : roots) { gray(root); workList.add(root); } while (!workList.isEmpty()) { Object obj = workList.poll(); // 取出下一个要处理的对象 blacken(obj); // 把这个对象变成黑色 for (Reference ref : getReferencesFrom(obj)) { // 获取该对象指向的所有其他对象 if (isWhite(ref.target)) { // 如果目标还是白色的就把它改成灰色并加进去 gray(ref.target); workList.add(ref.target); } } } // 清除所有的白色对象 collectGarbage(); } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值