匠心精神 - 良心品质腾讯认可的专业机构-IT人的高薪实战学院

咨询电话:4000806560

Golang内存管理:GC算法剖析

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的性能。