• 垃圾回收之并发情况下如何确定对象可达


    垃圾回收之并发情况下如何确定对象可达

    首先介绍下三色标记法:JVM中是通过三色标记法来确定哪些对象需要被回收,把遍历对象图过程中遇到的对象,按照“是否访问过”这个条件标记成一下三种颜色:

    • 白色
      表示对象尚未被垃圾收集器访问过,显然在垃圾收集刚开始,所有对象都是白色的。
    • 黑色
      表示对象已经被访问过,并且该对象的所有的 直接引用到的对象 都被访问过。
    • 灰色
      表示对象已经被访问过,但是该对象 至少有一个直接引用对象 没有被访问到。(简单来说,就是垃圾收集器还没有遍历完这个对象的所有直接引用的对象)

    开始讲本文之前,先举个并发标记的例子给大家说明一下:

    • 1
    graph LR A[root 黑] -->B(2 - 灰) B --> C(3 - 白)
    • 2
    graph LR A[root 黑] -->B(2 - 灰) B --> |XX|C A --> C(3 - 白)

    如上图:

    • 1
      并发标记阶段,GC root一开始都是黑色的,因为在初始标记阶段已经标记了root能直接关联的所有对象,所以在并发阶段开始时,root对象都是黑色的,而root对象直接关联的对象是 灰色 的。
    • 2
      在这一步,垃圾回收器还没来的及扫描 2 号灰结点的所有直接引用的结点,用户线程此时执行:
        root黑.field3白 = 2灰.field3白; 
        2灰.field3白 = null;  // 灰色 断开引用 白色
    

    那么转到GC线程执行时,此时3号结点因为只有root结点引用他,但是root结点已经是黑色的了,所以不会再扫描root结点的直接引用结点了,那么3号结点将一直是白色,在回收阶段3号结点将会被 回收,按道理来说,3号结点不应该被回收,因为他还在被root结点引用着,所以这将会造成一个致命的问题。

    我们可以看下造成这种问题的必要条件为:

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

    因此我们要解决上述问题,只要破坏上面两个必要条件中的任意一个即可,JVM实现了两种解决方案:增量更新(Incremental Update,CMS使用这种)和原始快照(Snapshot at the begin,即SATB;G1使用这种)。

    • 1
      增量更新破坏的是上面的第一个条件:当黑色对象插入新的指向白色对象的引用时,就把这个新的引用记录下来,等并发扫描结束之后,再把先前记录中的黑色对象拿出来为跟重新扫描一遍,相当于黑色对象插入新的引用后他自身就变灰了,那么也就不存在条件一中的 黑色对象

    • 2
      SATB破坏的时上面的第二个条件,当灰色对象要删除指向白色对象的引用时,就将这个要删除的引用记录下来作为快照,在并发扫描结束后,再将这些快照拿出来,将其灰色对象为根重新扫描一遍,扫描效果相当于没有删除白色对象的引用一样,自然就破坏了条件二中的 删除了全部从灰色对象到白色对象的直接或间接引用

  • 相关阅读:
    【笔记】算法图解
    redis两个主同时挂
    redis有间隔的kill 两个主:
    数据中心机房燃气分布式能源系统的作用是什么?
    C# DEBUG 调试信息打印及输出详解
    C# DEBUG 调试信息打印及输出详解
    C# DEBUG 调试信息打印及输出详解
    C# DEBUG 调试信息打印及输出详解
    多态中的题目分析题
    多态中的题目分析题
  • 原文地址:https://www.cnblogs.com/leonandyou/p/15957533.html
Copyright © 2020-2023  润新知