双/三色标记法的垃圾回收(GC)原理解析和缺陷解决方案(Go,Lua以及jvm的CMS和G1垃圾回收器中使用的回收算法)

标记-清除算法

go和lua虚拟机以及jvm的CMS和G1垃圾回收器的回收算法的思想均来自于标记-清除算法(Mark-Sweep),它们的gc有重要的两部分:

1.从根节点遍历所有对象,如果可达到,则标记

2.遍历所有对象,如果没有标记,则destory对象

双色标记法

在lua5.1之前,lua采用的是二色标记法,

第一遍扫描对象,并标记扫描到的对象为黑色,第二遍时候将白色对象destory掉

在这里插入图片描述

这个过程没法中断,如果在gc的时候创建完新的对象,那么在最后destory清算的时候,这个白色对象显然是没法判断是无法到达的还是新创建出来的

于是为了防止创建的新的白色对象对gc过程产生干扰,干脆就让程序停下来,就不会产生干扰了,但是代价是程序停顿,影响主线程,显然这种方式和不适用了

于是后面有了更先进的三色标记法

三色标记法

在lua5.1之后和go语言以及jvm的CMS和G1垃圾回收器使用的是三色标记法

下面给出它的简易回收原理

三色:

白色:对象没有被垃圾回收器访问时候标记为白色

灰色:这个对象正处在被扫描,但是它所有引用都没访问完的时候被标记为灰色

黑色:当一个对象的所有引用都被扫描了以后的时候,这个对象被标记为黑色

标记过程:

1.从根集开始遍历

2.遍历到的白色对象push入栈并标黑,遍历到灰色和黑色对象则跳过

3.从栈中pop出一个灰色对象,标记为黑色,并将这个节点执行步骤2

4.栈空的时候,将白色对象都destory

实例解析:

当开始的时候,根节点为黑色,可见,B和D对象是不可达到的位置

 

 从根节点遍历,遍历到C,将C标记为灰色,开始遍历C

 遍历到E,将其变为灰色,开始遍历E,但是没有可遍历对象,就将其变为黑色

 

 同理也将F变为黑色

 C的所有节点遍历完成,将C变为黑色

当没有灰色对象的时候(当灰色对象栈清空的时候),将白色对象destory

当这样就完成了gc

 注意到和双色标记法不同的是,这次判断条件是当灰色对象没有的时候进行gc,那时候的白色对象就一定是可以安全回收的对象了

三色标记法的隐患

在扫描B的节点的时候,B节点变为灰色,当扫描B的其他节点时候

 C在这时候引用变为A,那么B扫不上C,自己变黑,但是A已经不会再次扫描,C就被误当为“不可达节点”给destory掉,显然是不对的

这个问题的核心点有两个

1.灰色和白色断开
2.黑色和白色建立引用

为了解决上面的问题,在java的G1回收器和CMS垃圾回收器中分别从1和2两个方面入手给了两种解决方案:

G1的方法叫做原始快照(SATB)算法

原始快照是将灰色对象断开到白色对象的引用关系记录下来,扫描结束后根据记录以记录的灰色对象为根重新扫描一次

CMS的增量更新(Incremental Update)算法

增量更新是将黑色和白色建立引用的过程记录下来,根据这些记录以被记录的黑色对象为根重新扫描一次,用的是写屏障技术(write barrier)

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Lua 中,垃圾收集(Garbage Collection, GC)是一个自动内存管理机制,用于释放不再使用的内存。Lua 的默认 GC 会跟踪值类型的引用,当没有其他变量引用某个对象时,该对象会被回收LuaJIT 和 Xlua 这两个库对 LuaGC 特性提供了不同的优化和扩展: 1. LuaJIT:它是 Lua 的一个高性能版本,其 GC 实现更为高效。LuaJIT 使用了一个增量式 GC,这意味着它可以边执行代码边回收内存,而且它的“轻量级”线程模型也减少了 GC 对性能的影响。LuaJIT 另外还支持一种名为“惰性 GC”的模式,可以在脚本执行期间推迟垃圾收集直到必要时才进行。 2. Xlua:这是一个基于 LuaJIT 的扩展库,它提供了一种更高级别的接口来简化 C/C++ 与 Lua 的交互。Xlua 在一定程度上可以帮助管理和优化内存分配,比如它可能会有自己的内存池或者缓存策略来减少 GC 的频率。同时,Xlua 也可能提供了额外的功能来更好地控制 GC 的行为,比如显式的对象标记或资源清理。 关于如何使用这些库来处理值类型 GC 或内存管理,通常的做包括: - 在需要时手动释放 Xlua 提供的内存资源。 - 使用 Xlua 的 API 标记特定对象为不被 GC 回收,或者在适当的时间触发 GC。 - 如果 LuaJIT 被选为底层引擎,可能需要了解它的 GC 设置,并调整以适应特定应用的需求,例如设置延迟 GC
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值