GC算法-增量式垃圾回收

概述

增量式垃圾回收也并不是一个新的回收算法, 而是结合之前算法的一种新的思路.

之前说的各种垃圾回收, 都需要暂停程序, 执行GC, 这就导致在GC执行期间, 程序得不到执行. 因此出现了增量式垃圾回收, 它并不会等GC执行完, 才将控制权交回程序, 而是一步一步执行, 跑一点, 再跑一点, 逐步完成垃圾回收, 在程序运行中穿插进行. 极大地降低了GC的最大暂停时间.

实现

增量式垃圾回收只是提出了这样的一个概念, 并没有限定如何去实现. 想必也有不同的实现思路吧.

三色标记算法#

此算法将对象做不同的标记

  • 白色: 未搜索过的对象
  • 灰色: 正在搜索的对象
  • 黑色: 搜索完的对象

这里的颜色只是一种虚构的概念, 就是在对象上打tag.

在GC开始执行时, 所有对象都是白色的, 然后将根集合的对象放到栈中, 并标记为灰色, 依次处理. 将对象从栈中取出, 递归搜索所有子对象, 并标记为灰色, 当子对象搜索完后, 就将对象标记为黑色. 这样, 当一个对象搜索完后, 该对象及其关联的所有子对象就都是黑色的了. 当标记阶段结束后, 所有活动对象都是黑色, 垃圾对象则是白色.

此算法就是通过这样, 逐步对对象进行标记.

三色标记应用于标记清除中

标记清除算法在标记阶段, 应用三色标记逐步标记, 每次搜索一定次数后, 就返回执行, 等待下次继续标记, 将标记分为小段穿插在程序中运行.

在清除阶段, 也可以设置一个次数, 每遍历一定数量的对象, 就返回等待下次继续.

三色标记不光可以应用于标记清除中, 也可以应用于其他标记算法中.

问题

你以为这就完了么? 天真, 想象一下这样的场景:

// 假设 c, d 是两个对象
$b->son = $d;
$b->son = $c;
// 在这个时候, 开始GC, 将d标记为白色, 将c标记为黑色. 返回
$b->son = $d;
// GC清除阶段, 将c对象保留, 将d对象回收

这样就出现问题了, 也就是说如果我已经对其进行过标记了, 但它在我标记之后进行了修改, 就会导致清除阶段的对象很可能不是当时的真实情况.

那么如何防止这种遗漏的标记呢? 简单粗暴一点, 每次更新指针的时候, 如果对象是白色的, 就将其涂成灰色, 放到待搜索的栈中, 之后重新对其进行标记. 这样就可以保证不会回收到引用的对象, 虽然可能会有一些遗漏对象没有回收, 但是 who care? 下一次再回收咯.

也有不同的写入屏障处理方法, 在更新对象时进行不同操作.

大概如此....

posted @   烟草的香味  阅读(876)  评论(0编辑  收藏  举报
编辑推荐:
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
阅读排行:
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
点击右上角即可分享
微信分享提示
主题色彩