你还不知道「并发下的三色标记」么?

1,223 阅读3分钟

这是我参与8月更文挑战的第10天,活动详情查看:8月更文挑战

首先我们重温知识点

判断对象失是否存活

==两种判断方法==

引用计数算法

  • 在对象中添加一个引用计数器,每当有一个地方引用它时
  • 计数器值就加一;当引用失效时,计数器值就减一;
  • 任何时刻计数器为零的对象就是不可能再被使用的。 ==引用计数算法的缺陷==
  • 如下面代码,两个对象互相引用导致无法回收♻️
  • 对象objA和objB都有字段instance,赋值令 objA.instance=objB及objB.instance=objA,
  • 除此之外,这两个对象再无任何引用,实际上这两个对象已 经不可能再被访问,
  • 但是它们因为互相引用着对方,导致它们的引用计数都不为零,引用计数算法也 就无法回收它们。
Test objA = new Test();
        Test objB = new Test();
        objA.instance = objB;
        objB.instance = objA;
        objA = null; 
        objB = null;

可达性分析算法

==基本思路==

  • 通过一系列称为“GC Roots”的根对象作为起始节点集,从这些节点开始,根据引用关系向下搜索,
  • 搜索过程所走过的路径称为“引用链”(Reference Chain),如果某个对象到GC Roots间没有任何引用链相连,
  • 或者用图论的话来说就是从GC Roots到这个对象不可达时,则证明此对象是不可能再被使用的。

三色标记📌

有三种颜色

  • 白色:代表对象还没有被垃圾收集器访问过,最开始所有都是白色,但是在结束阶段,如果还是白色,那么就不可达

  • 黑色:代表对象已经被垃圾收集器访问过,并且所有引用已经被扫描过,是安全存活的

  • 灰色:代表对象已经被垃圾收集器访问过,但是这个对象至少存在一个引用还没被扫描过

  • 最初的状态:只有GC Roots是黑色的

image.png

  • 扫描过程中,从黑色变为灰色

image.png

  • 扫描完成后,黑色就是活着的对象,白色就是已经消亡可以回收♻️ image.png
  • 但是如果现在用户线程在标记进行时并发修改了引用关系,灰色的引用被断开,又与黑色对象建立了引用

image.png

  • 切断以后黑色对象,因为黑色对象不会重新扫描,这样就会扫描结束后,被黑色引用的依然是白色,这个对象就「消失了」

image.png

对象消失情况

  • 当插入一条或多条从黑色对象到白色对象的新引用
  • 删除了全部从灰色到白色的直接或间接引用

两种解决方案

增量更新

  • 破坏第一个条件,当有黑色对象新的引用白色对象时,就把插入的引用记录下来,
  • 等并发扫描过后,再讲这些记录的应用关系中的黑色对象作为跟,重扫一遍
  • 其实可以理解成黑色对象一旦插入了只想白色对象的引用后,就变为灰对色象了,因为要让它保证继续扫 原始快照
  • 破坏第二个条件,要是有灰色要删除指向白色引用关系时,就将这个删除引用记录下来
  • 等并发扫描结束后,再将灰色对象为根,重扫一遍
  • 可以理解为记录删除引用,再以灰为根去扫