垃圾回收(四)可达性分析三色标记以及解决并发问题

544 阅读2分钟

「这是我参与11月更文挑战的第4天,活动详情查看:2021最后一次更文挑战

三色标记

为了更好的了解垃圾收集标记的过程,我们引入三色标记的概念。

什么是三色标记?

颜色含义
白色对象未被垃圾收集器访问过可达性分析刚开始时,未被访问的对象都是白色的可达性分析结束后,未被引用到的对象都是白色的
未命名文件 (2).png未命名文件 (5).png
黑色对象已被垃圾收集器访问过,且这个对象的引用都被扫描过
灰色对象被垃圾收集器访问过,但存在引用对象未被扫描到未命名文件 (6).png

并发问题

当用户线程与收集器标记并发工作时,收集器标记过程中,用户线程同时修改了引用关系,会出现两种情况

  1. 原本需要死亡的,被标记为存活。
  2. 原本需要存活的,被标记为死亡。

第一种情况问题不大,下一次垃圾回收时再清理掉就好了,但是第二种情况就很严重了。

下图展示第二种情况是怎么出现的:

未命名文件 (7).png

扫描结束后,就会导致A、B两个对象本应该存活,但被错误的标记为死亡。

未命名文件 (9).png

解决方案

后续Wilson通过理论证明,只要同时满足以下两个条件,就会产生"本应该存活的对象却消亡"情况。

  1. 赋值器插入了一条或多条黑色对象到白色对象的新引用。
  2. 赋值器删除了所有灰色对象到该白色对象的直接或间接引用。

针对这种情况,有两种解决方案

  1. 增量更新
  2. 原始快照
  1. 增量更新

破坏第一个条件,当黑色对象插入新的引用到白色对象时,就记录这个引用。当本次扫描结束时,将记录过的引用关系的黑色对象为根,重新扫描一次。可以理解为只要黑色对象插入了一条引用到白色对象时,黑色对象就会变成灰色对象,进行下一次的扫描。

  1. 原始快照

破坏第二个条件,当灰色对象要删除指向白色对象的引用时,就记录这个引用。当本次扫描结束时,将记录过的引用关系的灰色对象为跟,重新扫描一次。

虚拟机的记录操作都是通过写屏障进行的