千锋教育-做有情怀、有良心、有品质的职业教育机构
Golang内存管理:GC算法剖析
前言
作为一门高性能的编程语言,Golang内存管理一直是开发者们关注的重点。作为Golang工程师,不了解内存管理会使得我们的代码出现内存泄漏等问题。因此,本文旨在深入探讨Golang的GC算法。
1. Golang GC 算法分类
Golang目前使用的是三色标记和清除算法(3-color Mark and Sweep),和Java的标记清除算法类似,一般分为以下几个步骤:
1) 根搜索(Root scanning):从固定的根开始扫描调用关系,标记被引用的对象。
2) 标记(Marking):从根对象开始,遍历整个堆,将被引用的对象标记为黑色。
3) 清除(Sweeping):将所有未被标记的对象清除,并将空间恢复给空闲链表。
2. 标记算法原理
2.1 标记时机
Golang运行时会分配一部分内存作为heap(堆),当堆中的对象达到一定的比例后,就会触发GC,进行垃圾回收。
2.2 标记流程
* GC开始前,所有对象都是白色的,标记位为0。
* 然后从根出发,遍历所有对象,将其标记为灰色,标记位为1,放入灰色对象队列
* 遍历灰色对象队列,取出一个对象,将其标记为黑色,所有引用它的对象也被标记后,放入黑色对象队列。
* 如果队列为空,则标记结束,所有没被标记的对象都是垃圾,可以被回收了。
2.3 并发标记
在并发标记中,会出现三色标记问题,即黑色对象引用灰色和白色对象,在标记结束前,灰色和白色对象之间还有引用关系,这时不能将所有白色对象都回收掉。因此Golang引入了三色标记和清除算法。
3. 三色标记和清除算法
3.1 状态
Golang中的对象有三种状态:黑色、灰色、白色。
* 黑色:已标记为存活的对象。
* 灰色:已发现但未标记为存活的对象。
* 白色:未发现的对象。
3.2 标记
在标记过程中,首先将根对象标记为灰色,并将灰色对象入队。然后遍历灰色队列,将灰色对象标记为黑色,将灰色对象的引用的白色对象标记为灰色,入队。不断遍历灰色队列,直到队列为空。
3.3 清除
清除阶段中,将所有白色对象回收,并将黑色和灰色对象标记为白色。
4. 安全点和边界栈
为了避免在标记时,出现指向新生代对象的指针,Golang使用了安全点和边界栈。
安全点是Golang程序执行期间,在程序整个执行过程中的某一时刻,GC程序可以安全地执行垃圾回收操作的时刻。Golang GC会在每个安全点进行检查,如果发现条件满足,则启动GC,并在安全点结束时恢复GC。
边界栈用于记录函数的退出地址,避免遍历调用栈时出现指向新生代的指针。
5. 总结
Golang内存管理采用了三色标记和清除算法,在并发标记时,使用了状态标记和安全点的方法来保证垃圾回收的准确性和高效性。同时,Golang GC 内部还有一组边界栈数据结构,来防止指针指向新生代对象,提升了GC的性能。
上一篇
如何使用Go语言进行Web开发?下一篇
如何快速学习Golang专家建议相关推荐