go语言不需要手动管理内存;go语言内置内存管理功能(GC机制),是一种自动内存管理的机制。当程序向操作系统申请的内存不再需要时,垃圾回收主动将其回收并供其他代码进行内存申请时候复用,或者将其归还给操作系统,这种针对内存级别资源的自动回收过程,即为垃圾回收;而负责垃圾回收的程序组件,即为垃圾回收器。
php入门到就业线上直播课:进入学习
Apipost = Postman + Swagger + Mock + Jmeter 超好用的API调试工具:点击使用
本教程操作环境:windows7系统、GO 1.18版本、Dell G3电脑。
go语言不需要手动管理内存;go语言内置内存管理功能(GC机制),开发者不需要关心内存的申请和释放,这样为使用者带来极大的便利。
什么是GC,又有什么用?
GC,全称 Garbage Collection,即垃圾回收,是一种自动内存管理的机制。
当程序向操作系统申请的内存不再需要时,垃圾回收主动将其回收并供其他代码进行内存申请时候复用,或者将其归还给操作系统,这种针对内存级别资源的自动回收过程,即为垃圾回收。而负责垃圾回收的程序组件,即为垃圾回收器。
垃圾回收其实一个完美的 “Simplicity is Complicated” 的例子。一方面,程序员受益于 GC,无需操心、也不再需要对内存进行手动的申请和释放操作,GC 在程序运行时自动释放残留的内存。另一方面,GC 对程序员几乎不可见,仅在程序需要进行特殊优化时,通过提供可调控的 API,对 GC 的运行时机、运行开销进行把控的时候才得以现身。
在计算中,内存空间包含两个重要的区域:栈区 (Stack) 和堆区 (Heap);栈区一般存储了函数调用的参数、返回值以及局部变量,不会产生内存碎片,由编译器管理,无需开发者管理;而堆区会产生内存碎片,在 Go 语言中堆区的对象由内存分配器分配并由垃圾收集器回收
通常,垃圾回收器的执行过程被划分为两个半独立的组件:
-
赋值器(Mutator):这一名称本质上是在指代用户态的代码。因为对垃圾回收器而言,用户态的代码仅仅只是在修改对象之间的引用关系,也就是在对象图(对象之间引用关系的一个有向图)上进行操作。
-
回收器(Collector):负责执行垃圾回收的代码。
GC中的根对象
根对象在垃圾回收的术语中又叫做根集合,它是垃圾回收器在标记过程时最先检查的对象,包括:
-
全局变量:程序在编译期就能确定的那些存在于程序整个生命周期的变量。
-
执行栈:每个 goroutine 都包含自己的执行栈,这些执行栈上包含栈上的变量及指向分配的堆内存区块的指针。
-
寄存器:寄存器的值可能表示一个指针,参与计算的这些指针可能指向某些赋值器分配的堆内存区块。
在 Go 语言中,垃圾回收器实现的算法是一个并发的三色标记和扫描收集器
垃回收器与 Go 程序同时运行,因此需要通过一种写屏障算法来检测内存中的潜在变化。启动写屏障的唯一条件是在短时间内停止程序,即 “Stop the World”
写屏障的目的是允许收集器在收集期间保持堆上的数据完整性
1.1 实现原理
Go 语言的垃圾收集可以分成清除终止、标记、标记终止和清除四个不同的阶段,其中两个阶段会产生 Stop The World (STW)
清除终止阶段
- 暂停程序,所有的处理器在这时会进入安全点(Safe point)
- 如果当前垃圾收集循环是强制触发的,我们还需要处理还未被清理的内存管理单元
标记阶段 (STW)
-
将状态切换至
_GCmark
、开启写屏障、用户程序协助(Mutator Assists)并将根对象入队 -
恢复执行程序,标记进程和用于协助的用户程序会开始并发标记内存中的对象,写屏障会将被覆盖的指针和新指针都标记成灰色,而所有新创建的对象都会被直接标记成黑色
-
开始扫描根对象,包括所有 Goroutine 的栈、全局对象以及不在堆中的运行时数据结构,扫描 Goroutine 栈期间会暂停当前处理器
-
依次处理灰色队列中的对象,将对象标记成黑色并将它们指向的对象标记成灰色
-
使用分布式的终止算法检查剩余的工作,发现标记阶段完成后进入标记终止阶段
标记终止阶段 (STW)
- 暂停程序、将状态切换至
_GCmarktermination
并关闭辅助标记的用户程序 - 清理处理器上的线程缓存
清理阶段
-
将状态切换至
_GCoff
开始清理阶段,初始化清理状态并关闭写屏障 -
恢复用户程序,所有新创建的对象会标记成白色
-
后台并发清理所有的内存管理单元,当 Goroutine 申请新的内存管理单元时就会触发清理
1.2 三色标记法
三色标记算法将程序中的对象分成白色、黑色和灰色三类:
- 白色对象 — 潜在的垃圾,其内存可能会被垃圾收集器回收
- 黑色对象 — 活跃的对象,包括不存在任何引用外部指针的对象以及从根对象可达的对象
- 灰色对象 — 活跃的对象,因为存在指向白色对象的外部指针,垃圾收集器会扫描这些对象的子对象
三色标记垃圾收集器的工作原理很简单,可以将其归纳成以下几个步骤:
-
从灰色对象的集合中选择一个灰色对象并将其标记成黑色
-
将黑色对象指向的所有对象都标记成灰色,保证该对象和被该对象引用的对象都不会被回收
-
重复上述两个步骤直到对象图中不存在灰色对象