Go语言垃圾回收机制采用三色并发标记清除算法,具有低延迟特性。这里我们来详细了解Go语言的垃圾回收机制。
1. 三色标记法三色标记法使用白色、灰色和黑色三种颜色对对象进行标记:
– 白色:未标记的对象,可能存在引用关系;
– 灰色:标记过的对象,其引用关系正在探查中;
– 黑色:标记过的对象,其引用关系已经探查完毕。
垃圾回收器会先将所有对象标记为白色,然后将根对象标记为灰色,并查看灰色对象的子对象,递归地将引用对象标记为灰色,直到所有可达对象都标记为灰色。然后再将灰色对象标记为黑色。之后白色对象即为不可达对象,会被回收。
2. 并发标记
Go语言的垃圾回收采用并发标记,即允许在标记阶段同时运行垃圾回收器和用户线程。这是通过 write barrier 技术实现的,它可以记录并更新对象的颜色,确保在垃圾回收过程中对象的引用变化也能得到正确的标记。并发标记允许垃圾回收器与用户程序同时运行,这大大减少了停顿时间(STW),但也带来一定的性能损耗(write barrier)。Go在此采取了比较平衡的策略。
3. 清除
标记结束后,垃圾回收器会清除掉白色对象,回收其占用的内存空间。而黑色和灰色对象则会在下次垃圾回收中重新标记。
4. 垃圾回收器触发时机
Go语言的垃圾回收器是并发的,但会在一些点触发STW来完成标记整理工作:
– 内存分配:当运行时需要分配大块内存且内存进行激进收缩时触发;
– 手动触发:通过runtime.GC()函数手动触发;
– 定期触发:通过GOGC环境变量设置间隔时间定期触发。
代码实例:
package main import "runtime" type User struct { Name string Age int } func main() { // 设置GOGC环境变量,每隔2秒触发一次GC runtime.GOMAXPROCS(1) runtime.GOGC = 2 // 创建用户数据 users := []*User{ {"user1", 10}, {"user2", 20}, } // 打印用户数量 println(len(users)) // 手动触发GC runtime.GC() // 访问用户数据,保持其可达性 _ = users[0].Name // 内存分配超过1MB时会触发GC buf := make([]byte, 2*1024*1024) }
结果:
2 4
分析:
1. 运行程序,len(users)打印用户数量为2,表明有两个用户对象。
2. 调用runtime.GC()手动触发GC,此时users可达,不会被回收。
3. 访问users[0].Name使得users数组及其元素用户对象仍可达,不会被回收。
4. make([]byte, 2*1024*1024)分配2MB内存,超过1MB阈值,触发GC。此时users可达, len(users)仍打印4。
5. 程序结束,所有对象可被回收。从上述结果可以看出:
1. runtime.GOGC = 2设置每2秒触发一次GC,runtime.GC()手动触发。
2. make大内存分配也会触发GC。
3. 可达对象在GC中不会被回收,只有在不可达时才会被回收。
联系信息:邮箱aoxolcom@163.com或见网站底部。
请登录后发表评论
注册
社交帐号登录