首页 > 其他分享 >三色标记法

三色标记法

时间:2023-03-29 20:14:39浏览次数:32  
标签:黑色 快照 白色 对象 标记 扫描 引用

在遍历对象图的过程中,把需要遍历的对象按照“是否访问过”分为以下三种颜色。

  • 白色:表示对象尚未被垃圾回收器访问过。显然,在可达性分析刚刚开始的阶段,所有的对象都是白色的,若在分析结束的阶段,仍然是白色的对象,即代表不可达。
  • 黑色:表示对象已经被垃圾回收器访问过,且这个对象的所有引用都已经扫描过。黑色的对象代表已经扫描过,它是安全存活的,如果有其它的对象引用指向了黑色对象,无须重新扫描一遍。黑色对象不可能直接(不经过灰色对象)指向某个白色对象。
  • 灰色:表示对象已经被垃圾回收器访问过,但这个对象至少存在一个引用还没有被扫描过。
0 上图是在可达性分析的扫描过程中,如果只有垃圾回收线程在工作,那肯定不会有任何问题。 如果用户线程和GC线程并发执行时,就会出现对象消失的情况。如下图 0 看完上图,是不是有点理解了开头那个问题:为什么遍历对象图必须在一个保障一致性的快照中。
  • 如果不保障一致性,对象会消失。

如何解决这个问题?

一个叫Wilson的大佬,他在1994年在理论上证明了,当且仅当以下两个条件同时满足时,会产生"对象消失"的问题,原来应该是黑色的对象被误标为了白色:
  • 条件一:赋值器插入了一条或者多条从黑色对象到白色对象的新引用。
  • 条件二:赋值器删除了全部从灰色对象到该白色对象的直接或间接引用。
反过来想,是不是破坏其中一个条件,就不会存在对象消失的情况了吧。 因此,我们要解决并发扫描时的对象消失问题,只需破坏这两个条件的任意一个即可。由此分别产生了两种解决方案:增量更新(Incremental Update)原始快照(Snapshot At The Beginning,SATB)
  • 增量更新(Incremental Update):打破了第一个条件,在扫描过程中,如果黑色对象插入了新的白色对象引用,那么就将这些黑色对象记录起来作为GC Roots,在扫描结束的时候重新扫描以这些为Root的引用链。其实就可以很简单的理解成,在黑色对象插入新的白色对象引用以后,就重新变成了灰色对象。
  • 原始快照(Snapshot At The Beginning,SATB):打破了第二个条件。在扫描过程中,如果出现灰色对象删除白色对象的引用时,就将这些灰色对象记录下来。在扫描结束后,对这些灰色对象重新扫描一遍。
以上无论是对引用关系记录的插入还是删除通过“写屏障”来完成。
  • 增量更新使用的是写后屏障(记录插入后的新引用)
  • 原始快照使用的是写前屏障(记录删除后的前引用)
在HotSpot虚拟机中, 增量更新和原始快照这两种解决方案都有实际应用, 譬如, CMS是基于增量更新来做并发标记的, G1、 Shenandoah则是用原始快照来实现

标签:黑色,快照,白色,对象,标记,扫描,引用
From: https://www.cnblogs.com/zhengbiyu/p/17270160.html

相关文章