【面试八股总结】GC垃圾回收机制

news/2024/12/22 23:29:06/

        垃圾回收策略(Garbage Collection,GC)用于回收不再使用的内存,避免系统的内存被占满。Go1.3之前采用标记清除法, Go1.3之后采用三色标记法,Go1.8采用三色标记法+混合写屏障。

前置概念:

1)根对象:应用程序中可以直接或间接访问的对象,主要包括:

  • 全局变量:在程序编译期间就能确定,全局变量存在于程序的整个生命周期
  • 执行栈:Go语言中协程是分配在堆上,每个协程都含有自己的执行栈
  • 寄存器:寄存器的值可能表示一个指针,这些指针可能指向某些赋值器分配的堆内存区

2)STW(Stop-The-World):系统在执行特定操作时,暂停所有应用程序线程,直到某个特定的事件发生或处理完成。

1. 标记清除法

具体步骤:

1)首先从根对象出发,标记所有可达对象。

        这一过程通常使用深度优先搜索或广度优先搜索进⾏。标记的方式通常是将对象的标记位从未标记改为已标记。

2)在清扫阶段,遍历整个堆内存,将未被标记的对象视为垃圾,即不再被引用。所有未被标记的对象都将被回收,它们的内存将被释放,以便后续的内存分配。

        标记清除算法执行完清扫阶段后,可能会产生内存碎片,即一些被回收的内存空间可能是不连续的。为了解决这个问题,一些实现中可能会进行内存碎片整理。

总结:

        标记清除算法的主要优势是能够回收不再使用的内存,但它也有一些缺点,其中主要的缺点是清扫阶段可能会引起一定程度的停顿,因为在这个阶段需要遍历整个堆内存。另外,由于标记清除算法只关注“存活”和 “垃圾”两种状态,不涉及内存分配的具体位置,可能导致内存碎片的产生

2. 三色标记法

        三色标记是指将对象分为三种颜色:白色、灰色、和黑色。

(1)白色:代表最终需要清理的对象内存块

(2)灰色:待处理的内存块

(3)黑色:活跃的内存块

具体步骤:

1)初始时,所有对象都被标记为白色,表示它们都是未被访问的垃圾对象。

2)根搜索:从根对象开始搜索,所有根对象被标记为灰色,表示它们是待处理的对象。

3)标记阶段:从灰色对象开始,垃圾回收器遍历对象的引用关系,将其引用的对象标记为灰色,然后当前该对象标记为黑色。重复这一步骤,直到所有可达对象都被标记为黑色。

4)清扫阶段:在标记完成后,垃圾回收器会扫描堆中的所有对象,将未被标记的对象回收(释放其内存)。这些未被标记的对象被认为是不可达的垃圾。

5)内存返还:垃圾回收完成后,系统中的内存得以回收并用于新的对象分配。

总结:

        1)优点:在标记阶段,垃圾回收器采用并发标记的方式,与程序的执行同时进行。这意味着程序的执行不会因为垃圾回收停顿,减小了对程序性能的影响。

        2)缺点:如果对象的引用被用户修改了,那么之前的标记就⽆效了。        

        3)垃圾回收的触发条件通常是在分配新对象时,如果达到⼀定的内存分配阈值,就会触发垃圾回收。 另外,⼀些特定的事件(如系统调用、网络阻塞等)也可能触发垃圾回收。       

3. 三色标记法+混合写屏障

        屏障技术可以理解为一种回调机制,在程序的某种执行过程中加一个判断机制,满足判断机制则执行回调函数,类似于钩子函数(Hook)。

        实际上,垃圾回收机制只用于回收堆上的内存,栈中的内存如局部变量、函数调用等会在调用结束后自动释放。也就是说,屏障机制只能作用于堆对象。屏障机制分为插入写屏障和删除写屏障:

  • 插入写屏障实现了强三色不变性,给对象添加引用关系时触发
  • 删除写屏障实现了弱三色不变性,删除对象引用关系时触发
  • 强三色不变性强制性的不允许黑色对象引用白色对象;
  • 弱三色不变性允许黑色对象引用白色对象,但是白色对象必须存在其他灰色对象对它的引用。

插入写屏障:每当一个对象被引用,就会触发判断:如果这次操作是一个白色对象被黑色对象引用,就把这个白色对象标记为灰色

删除写屏障:每当一个对象被删除时,就会触发判断:如果是一个灰色对象引用的白色对象被删除,那么就把这个白色对象标记为灰色

插入写屏障和删除写屏障都有各自的短板:

  • 插入写屏障结束时需要 STW(标记清除)重新扫描栈

  • 删除写屏障回收精度低,在开始时需要 STW 扫描整个堆栈记录初始快照

        基于插入写屏障和删除写屏障在结束时需要STW来重新扫描栈,带来性能瓶颈。混合写屏障分为以下四步:

  1. GC开始时,将栈上的全部对象标记为黑色(不需要二次扫描,无需STW);

  2. GC期间,任何栈上创建的新对象均为黑色 

  3. 被删除引用的对象标记为灰色 

  4. 被添加引用的对象标记为灰色

        因此,一次完整的GC分为四个阶段:

  1. 准备标记(需要STW),开启写屏障。
  2. 开始标记
  3. 标记结束(STW),关闭写屏障
  4. 清理(并发)

总结:

        标记清除法需要一次全局 STW,先标记可达对象,再清除所有的不可达对象,性能很差;

        三色标记法身无法在并发条件下正确执行,单独使用也需要 STW 才能保证正确性;

        为了优化这一过程,避免全局 SWT,引入了插入写屏障,插入写屏障是一种触发机制,每当一个对象被引用时,如果是黑色对象引用白色对象,就把这个白色对象置灰,但是由于屏障机制无法作用到栈对象,为了避免与栈相关的活跃对象被错误回收,需要在三色标记法结束后,对栈做一次 STW,清除掉垃圾对象;插入写屏障虽然优化了全局 SWT,但是每次GC也需要对栈上的一次 STW;

        为了解决这一问题,最终的方案是混合写屏障,混合写屏障的触发机制有两个:被删除的对象会被标记为灰色,被添加的对象会被标记为灰色;同时在开始时会把栈上所有可达对象置黑,栈上对象被创建时也会置黑。这样就记录了栈上的对象状态,避免了错误回收活跃对象;

        混合写屏障结合了插入写屏障和删除写屏障的优点,避免了在插入写屏障结束后需要进行全栈扫描的性能问题,实现了更高效的垃圾回收机制。

参考:代码随想录、Go语言的垃圾回收机制,图文并茂 一篇搞懂!_go垃圾回收-CSDN博客


http://www.ppmy.cn/news/1526471.html

相关文章

保姆级离线+windows环境+大模型前端UI安装(二)

看到很多文章采用docker在windows环境安装python或者是linux环境再装webui的,感觉比较麻烦,不够简洁,本文采用nodejs,来作为客户端引擎。 这篇只讲客户端安装,需要安装后端大模型及其运行的可以参考第一篇&#xff1a…

WPF 依赖属性与附加属性(面试长问)

在WPF中,**依赖属性(Dependency Property)和附加属性(Attached Property)**是WPF依赖属性系统的重要组成部分。它们虽然都基于依赖属性系统,但用途、定义方式和使用场景有显著差异。以下是两者的详细解释及…

Spark_natural_join

在 Apache Spark 中,NATURAL JOIN 和 INNER JOIN 是两种不同的连接操作,它们在合并数据集时有不同的行为和用途。 INNER JOIN INNER JOIN 是一种基本的连接操作,它返回两个数据集(DataFrame 或表)中匹配指定连接条件…

计算机毕业设计 乡村生活垃圾管理系统的设计与实现 Java+SpringBoot+Vue 前后端分离 文档报告 代码讲解 安装调试

🍊作者:计算机编程-吉哥 🍊简介:专业从事JavaWeb程序开发,微信小程序开发,定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事,生活就是快乐的。 🍊心愿:点…

SprinBoot+Vue社区生鲜团购系统的设计与实现

目录 1 项目介绍2 项目截图3 核心代码3.1 Controller3.2 Service3.3 Dao3.4 application.yml3.5 SpringbootApplication3.5 Vue 4 数据库表设计5 文档参考6 计算机毕设选题推荐7 源码获取 1 项目介绍 博主个人介绍:CSDN认证博客专家,CSDN平台Java领域优质…

面试问题001

进程和线程的区别 进程是资源分配和调度的基本单位。 线程是程序执行的最小单位,线程是进程的子任务,是进程内的执行单元。 一个进程至少有一个线程,一个进程可以运行多个线程,这些线程共享同一块内存。 资源开销: 进…

无人机PX4飞控ROS应用层开发:MAVROS 功能包介绍与飞控消息汇总(一)

概述 这个软件包提供了针对各种自动驾驶仪(如PX4,Ardupilot)使用 MAVLink 通信协议的通信驱动程序。 此外,它还提供了用于地面控制站(例如 QGroundControl)的 UDP MAVLink 桥接功能。 通常与PX4的offboard模式联合使用 Offboard控制背后的想…

俄罗斯方块——C语言实践(Dev-Cpp)

目录 1、创建项目(尽量不使用中文路径) 2、项目复制 3、项目配置 ​1、调整编译器 2、在配置窗口选择参数标签 3、添加头文件路径和库文件路径 4、代码实现 4.1、main.c 4.2、draw.h 4.3、draw.c 4.4、shape.h 4.5、shape.c 4.6、board.h 4.7、board.c 4.8、cont…