再难也要学的JVM垃圾回收器:并发标记清除回收,并发回收的难点

并发回收的难点

并发回收的难点在于Mutator和Collector同时执行,Mutator会修改对象的引用关系,导致Collector无法正确处理所有对象,进而导致部分对象丢失。并发回收中涉及并发标记和并发转移,两者遇到的问题比较类似。这里以并发标记为例,介绍如何增强算法从而保证算法的正确性。

并发标记的主要问题是垃圾回收器在标记对象的过程中Mutator可能正在改变对象引用关系图,从而造成漏标和错标。错标不会影响程序的正确性,只会造成所谓的浮动垃圾。但漏标则会导致可达对象被当作垃圾收集,从而影响程序的正确性。为了区别对象所处的不同状态,引入了三色标记法。

三色标记法

三色标记法是一个逻辑上的抽象:白色(White)表示还没有被收集器标记的对象,灰色(Gray)表示自身已经被标记到,但其拥有的成员变量引用到别的对象还没有处理,黑色(Black)表示自身已经被标记到,且对象本身所有的成员变量引用到的对象也已经被标记。

对象在并发标记阶段会被漏标的充分必要条件是:

Mutator插入了一个从Black对象到该White对象的新引用,因为黑色对象已经被标记,如果不对黑色对象重新处理,那么白色对象将被漏标,造成错误。

Mutator删除了所有从Gray对象到该White对象的直接或者间接引用,因为灰色对象正在标记,成员变量引用的对象还没有被标记,如果这个引用的白色对象被删除了(引用发生了变化),那么这个引用对象也有可能被漏标。

因此,要避免对象的漏标,只需要打破上述两个条件中的任何一个即可。所以在并发标记的时候对应也有两种不同的实现,分别是读屏障和写屏障。屏障技术是在读或者写操作时执行一段代码,其目的是调整对象的颜色从而保证正确性。但是Mutator中读操作远多于写操作,所以读屏障的效率一般低于写屏障的效率。下面通过一个例子演示并发标记导致的问题以及解决思路。

难点示意图

为了直观地理解并发标记的难点,下面用一个示意图来说明。并发标记的中间状态如图1所示。

图1 并发标记的中间状态

图1中有4个对象,3种颜色分别是黑色、灰色和白色。假定对象1和对象2都可以通过根对象到达并且标记完成,所以为黑色。而对象3本身已标记完成,但是其成员变量(指向对象4)尚未完成标记,对象3入栈待处理,所以对象3为灰色,对象4为白色。如果此时并发标记线程让出CPU,Mutator执行并修改了引用关系。对象3的成员变量设置为NULL,对象2的成员变量指向对象4,则对象的引用关系图如图2所示。

图2 Mutator运行导致关系变更

这时并发线程重新获得执行,将会发生什么?对象2已经变成黑色,说明成员变量都标记完了。对象3为灰色表示有待处理成员变量,但是其成员变量已经设置为NULL,所以无须处理。那么对象4怎么办?如果不进行额外的处理就会导致漏标。处理方法如下:

1)读屏障:对读到的对象进行标记。

2)写屏障:在写(修改)对象时调整对象的颜色,主要方法有以下两种。

增量更新算法关注对象引用插入,重新标记更新的对象,确保不存在黑色对象指向白色对象的引用。

SATB关注引用的删除,即在对象被赋值前,把老的被引用对象记录下来(所以相当于建立一个内存切片),然后以这些对象为根重新标记一遍,确保灰色对象指向的白色对象都会被标记。

读屏障通常是Mutator在读操作(注意写操作也包含了读操作)时直接帮助Collector进行标记;写屏障通常是Mutator在写操作时记录需要重新标记的对象,由Collector负责再次执行标记。因为读、写操作数量不同,不同的实现采用不同的方式,以便在内存消耗和执行时间之间取得平衡。

读屏障处理

对读到的对象进行标记,这里只关注对象4,忽略其他的读操作。在读屏障中通常由Mutator帮助Collector执行标记动作,对于对象4来说,相当于把对象4变成了灰色。使用读屏障时,对象引用关系图中对象的颜色如图3所示。

图3 读屏障对象颜色示意图

使用读屏障时所有读操作都会执行屏障,只不过已经完成标记的(黑色颜色对象)不需要执行具体的标记动作,但是需要检查对象的颜色,由此会带来不小的成本。

写屏障之增量标记

被更新的黑色对象标记成灰色,打破第一个条件(即不存在黑色对象指向白色对象)。使用增量标记时对象引用关系图中对象的颜色如图4所示。

图4 增量标记使用的写屏障示意图

写屏障之SATB标记

对对象赋值前的值进行标记,可保证修改前的对象都得到标记的机会(保证灰色对象引用的对象都会得到标记)。使用SATB标记时,对象引用关系图中对象的颜色如图5所示。

图5 SATB算法的写屏障示意图

  • 21
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值