Golang-垃圾回收-三色标记法

1.垃圾回收回顾

1.1 概念:

垃圾回收算法目前常见的也就那么几种,如:标记-清除、标记-复制、标记-整理。在此基础上可以采用分代管理(新生代、老年代、永久代),每代采用不同的垃圾回收算法,以提高整体的回收效率。

1.2 步骤:
  • 标记存活对象和可回收对象(可达性分析算法、计数法)
  • 对可回收对象采用进行垃圾回收处理
1.3 标记方法:
  • 可达性分析算法:可达性分析算法是以根对象集合(GC Roots)为起始点,按照从上至下的方式进行搜索,搜索所走过的路径称为引用链(Reference Chain),通过判断对象与GC Roots之间是否有引用链相连来判断该对象是否需要回收,如果目标对象没有任何引用链相连,则是不可达的,就意味着该对象已经死亡,可以标记为垃圾对象。
  • 引用计数算法:为每一个对象分配一个计数器,当这个对象被另一个对象引用时,这个计数器就加一;当被另一个对象取消引用时,计数器就减一。当这个计数器的值为零时,就表示当前对象没有被任何对象所引用,那么这个对象就可以被垃圾回收器进行回收了。该方法实现起来非常简单,但是有一个致命的缺点,那就是不能解决各对象之间循环引用的问题。

2.三色标记法

2.1 基本概念:

根据可达性分析,从GC Roots开始进行往下进行,可达的则为存活对象
在这里插入图片描述
我们把搜索过程中遇到的对象,按是"否访问过"这个条件标记成以下三种颜色:

  • 白色:尚未访问过。
  • 黑色:本对象已访问过,而且本对象引用到的其他对象也全部访问过了。
  • 灰色:本对象已访问过,但是本对象引用到的其他对象尚未全部访问完。
2.2 过程
  1. 开始时,将所有的对象都加入到【白色集合】中去。
  2. 将GC roots从【白色集合】中转移到【灰色集合】中去
  3. 将GC roots直接引用到的所有对象转移到【灰色集合】中,同时将GC roots转移到【黑色集合】中去。
  4. 从【灰色集合】中获取对象:
    将该对象 引用到的 其他对象 全部挪到 【灰色集合】中;
    将该对象 挪到 【黑色集合】里面。
  5. 重复步骤3,直至【灰色集合】为空时结束。
  6. 结束后,仍在【白色集合】的对象即为GC Roots 不可达,可以进行回收。

第一步程序将会Stop The World,这时候对象间的引用是不会发生变化的,可以轻松完成标记。而当需要支持并发标记时,即标记期间应用线程还在继续跑,对象间的引用可能发生变化,多标漏标的情况就有可能发生。

2.3 多标-浮动垃圾

在这里插入图片描述
如上图所示,假设引用链已经走到E(灰色集合)了,这个时候应用执行了objD.fieldE = null,此时D与E之间的引用链将断开,此刻之后,对象E/F/G是“应该”被回收的。然而因为E已经变为灰色了,其仍会被当作存活对象继续遍历下去。最终的结果是:这部分对象仍会被标记为存活,即本轮GC不会回收这部分内存。
这部分本应该回收 但是 没有回收到的内存,被称之为“浮动垃圾”。浮动垃圾并不会影响应用程序的正确性,只是需要等到下一轮垃圾回收中才被清除。

另外,针对并发标记开始后的新对象,通常的做法是直接全部当成黑色,本轮不会进行清除。这部分对象期间可能会变为垃圾,这也算是浮动垃圾的一部分。

2.4 漏标-读写屏障

在这里插入图片描述
如上图所示,假设搜索到引用链已经走到E(灰色集合),此时执行代码:

var G = objE.fieldG; 
objE.fieldG = null;  // 灰色E 断开引用 白色G 
objD.fieldG = G;  // 黑色D 引用 白色G

此时切回GC线程继续跑,因为E已经没有对G的引用了,所以不会将G放到灰色集合;尽管因为D重新引用了G,但因为D已经是黑色了,不会再重新做遍历处理。
最终将会导致G会一直停留在白色集合中,最后被当作垃圾进行清除。这直接影响到了应用程序的正确性,是不可接受的。

漏标需同时满足以下两个条件:
1.【灰色集合】对象断开对【白色集合】对象的引用。
2.【黑色集合】对象在GC期间重新引用【白色对象】

解决漏标—读写屏障

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值