golang的垃圾回收

垃圾回收的几种机制

引用计数

过程:

1)当对象被创建时,初始化计数器为1

2)当更新指针时,新指向的对象引用计数加一,旧对象引用计数减一,如果为0则回收掉,放入空闲队列,并且递归的去 更新

优点:

1)实时性高,当对象引用计数为0时,立即回收

2)垃圾回收过程中应用无需挂起

缺点:

1)指针的更新需要手动的去操作,当前对象的引用计数为0时,需要递归更新对象的引用计数

2)无法解决循环引用问题(自循环引用、相互循环引用、多循环引用)

解决循环引用的方法:

1)避免产生循环引用

2)在合适的时机,手动显示的断开

3)弱引用 weak_ptr

标记清除

从root开始一层层扫描,root指当前所有goroutine的栈和全局数据区的变量(主要是这两个)

扫描过程中把所有可达的object标记出来,未被标记的object就需要清除,清除后的object会被放回到mcache中以备后续分配使用

整个过程需要stop the worl,挂起所有用户goroutine

三色标记

对于黑色的object,如果标记期间发生了写操作,写屏障会在真正赋值前将新对象标记为灰色

标记过程中,新分配的object,会先被标记成黑色再返回

对上的object被赋值给一个栈上的指针,写屏障是检测不到的,所以标记的最后阶段,还会回头重新扫描一下所有的栈空间,确保没有遗漏

混合写屏障

不需要最后回头重新扫描所有goroutine的栈空间了,是的整个GC过程中的stw可以忽略不计了

但也带来一些代价,如果C未被赋值给L,却被置灰,只能等下一次GC的时候再进行回收

还有一种情况,当GC过程中新创建的对象(被置黑),也会被下次回收

节点复制

分代收集(新生代和老年代)

将堆划分为两个多个称为代的空间,新创建的对象放在新生代中,随着垃圾回收的重复执行,生命周期长的对象会被提升到老年代中

golang的GC

1)1.3版本以前,go runtime在一定条件下(内存超过阈值或定期2min)暂停所有任务的执行,进行mark&sweep操作,操作完成后启动所有任务的执行,整个过程需要stw,挂起所有goroutine

2)1.3版本开始,go runtime分离了mark和sweep操作,也是先暂停所有任务执行并启动mark,mark完之后就重新启动被暂停的任务,让sweep任务和普通协程任务一样并行的一起执行。如果运行在多核处理器上,go会试图让gc任务放到单独的核心上运行,尽量不影响业务代码的执行,标记过程stw,清除过程并行

3)1.4版本,runtime很多代码取代了原生的c语言,采用go语言实现

4)1.5版本,三色标记清除垃圾收集器(非分代的、非移动的、并发的),三色标记法的mark操作是可以渐进执行的,而不需要每次都扫描整个内存空间,可以减少stop the world的时间,三色标记+写屏障

5)1.8版本,Hibrid write Barrier(混合写屏障),不需要最后回头重新扫描所有goroutine的栈空间

GC何时被触发

1)堆上内存达到一定数值

2)每隔2min,强制触发

3)用户手动触发,使用runtime.GC()强制触发

相关推荐
hrhcode16 分钟前
【java工程师快速上手go】二.Go进阶特性
java·golang·go
Tomhex2 小时前
Go字符串拼接最佳实践
golang·go
zs宝来了3 小时前
Go 内存管理:三色标记 GC 与逃逸分析
golang·go·后端技术
zs宝来了7 小时前
Go pprof 性能剖析:CPU、内存与锁分析
golang·go·后端技术
深挖派9 小时前
GoLand 2026.1 安装配置与环境搭建 (保姆级图文教程)
后端·golang·编辑器·go·goland
用户0953675158310 小时前
从 DeepSeek 那里了解到的 Go
go·deepseek
zs宝来了11 小时前
Go Context:上下文传播与取消机制
golang·go·源码解析·后端技术
zs宝来了12 小时前
Go Channel 原理:环形缓冲区与同步机制
golang·go·源码解析·后端技术
王码码20351 天前
Go语言中的Elasticsearch操作:olivere实战
后端·golang·go·接口
Tomhex1 天前
Go语言import用法详解
golang·go