自动垃圾回收是Go语言最大的特色之一。所谓垃圾就是不再需要的内存块,这些垃圾如果不清理就没办法再次被分配使用,在不支持垃圾回收的编程语言里,这些垃圾内存就是泄漏的内存。
垃圾回收机制
自动找出并释放不再使用的内存空间机制,就称为垃圾回收机制(Garbage Collection,简称GC)。
垃圾回收的核心就是标记出哪些内存还在使用中(被引用到),哪些内存不再使用了(未被引用),把未被引用的内存回收,以供后续内存分配时使用。
栈空间和堆空间
每个线程都有独立的栈空间,栈空间用于保存调用函数的数据。 堆空间是程序中一块独立的空间,从堆空间分配的数据可以被程序中的所有函数和线程访问,并且不会随函数返回与线程结束释放。
值类型和引用类型
值类型的对象本身存储值,而引用类型的对象本身存储内存地址,值存储在内存地址指向的空间中。
值类型与引用类型的对象本身存储在栈空间还是堆空间是根据定义的位置而定的。
值类型的对象会根据定义的位置隐式分配与释放。
引用类型的对象需要通过new关键字显示分配,new会从堆空间申请一块空间用于保存值,然后返回空间的开始地址。
三色标记法
前置知识
三色标记法将对象分为以下三种:
- 白色:不确定对象(默认色)
- 黑色:存活对象
- 灰色:存活对象,子对象待处理
根对象:
- 全局变量
- 执行栈
- 寄存器
步骤
- 开始时,将所有对象加入白色集(需要STW,STOP THE WORLD)
- 先将根对象标记为灰色。再将一个对象从灰色集合中取出,遍历其子对象放入到灰色集合(同时将取出的对象染为黑色)。=
- 直到灰色集为空、最后的白色就是都要清除的
缺陷
若对象引用被修改,之前的标记就无效。因此Go采用了混合写屏障技术,当对象新增或更新就着为黑色。
完整的GC过程
- 准备标记(需要STW),开启写屏障
- 开始标记
- 标记结束(需要STW),关闭写屏障
- 清理(并发)
混合写屏障
- GC开始时,将栈上全部对象标记为黑色(无STW)
- GC期间,如何栈上创建的新对象均为黑色
- 被删除引用的对象标记为灰色
- 清理(并发)