既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Go语言开发知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新
2. 根对象是什么
根对象又叫根集合,它是垃圾回收器在标记过程最先检查的对象,包括:
- 全局变量:程序在编译期就能确定的那些存在于程序整个生命周期的变量。
- 执行栈:每个 goroutine 都包含自己的执行栈,这些执行栈上包含栈上的变量及指向分配的堆内存区块的指针。
- 寄存器:寄存器的值可能表示一个指针,参与计算的这些指针可能指向某些赋值器分配的堆内存区块。
3. GC两种形式
- 追踪式GC
从根对象出发,根据对象之间的引用信息,一步步推进直到扫描完毕整个堆并确定需要保留的对象,从而回收所有可回收的对象。Go、 Java、V8 对 JavaScript 的实现等均为追踪式 GC。
- 引用计数式GC
每个对象自身包含一个被引用的计数器,当计数器归零时自动得到回收。因为此方法缺陷较多,在追求高性能时通常不被应用。Python、Objective-C 等均为引用计数式 GC。
4. GC实现方式
4.1 追踪式:
- 标记清扫:从根对象出发,将确定存活的对象进行标记,并清扫可以回收的对象。
- 标记整理:为了解决内存碎片问题而提出,在标记过程中,将对象尽可能整理到一块连续的内存上。
- 增量式:将标记与清扫的过程分批执行,每次执行很小的部分,从而增量的推进垃圾回收,达到近似实时、几乎无停顿的目的。
- 增量整理:在增量式的基础上,增加对对象的整理过程。
- 分代式:将对象根据存活时间的长短进行分类,存活时间小于某个值的为年轻代,存活时间大于某个值的为老年代,永远不会参与回收的对象为永久代。并根据分代假设(如果一个对象存活时间不长则倾向于被回收,如果一个对象已经存活很长时间则倾向于存活更长时间)对对象进行回收。
4.2 引用计数式
- 引用计数:根据对象自身的引用计数来回收,当引用计数归零时立即回收。
5. GC的历史及演进
Go v1.3之前标记-清除法(mark and sweep)
GO v1.5之后三色标记法
GO v1.5-v1.7三色标记法+开启写屏障
Go v1.8三色标记法+结合写屏障和删除屏障的混合写屏障法
6. 标记-清除法
标记清除法分为两个步骤:
- 标记:从根对象出发,递归遍历,将被引用的对象打上标记;会先STW(STW,Stop The World),暂停整个程序的全部运行线程。
- 清除:回收未打标记的对象,即回收内存资源,然后恢复运行线程。
通过STW保证GC期间标记对象的状态不能变化,整个程序都要暂停掉,在外部看来程序就会卡顿。
如下图所示,内存空间中包含多个对象,我们从根对象出发依次遍历对象的子对象并将从根节点可达的对象都标记成存活状态,即 A、C 和 D 三个对象,剩余的 B、E 和 F 三个对象因为从根节点不可达,所以会被当做垃圾:
标记阶段结束后会进入清除阶段,在该阶段中收集器会依次遍历堆中的所有对象,释放其中没有被标记的 B、E 和 F 三个对象并将新的空闲内存空间以链表的结构串联起来,方便内存分配器的使用。
7. 三色标记
为了解决原始标记清除算法带来的长时间 STW,多数现代的追踪式垃圾收集器都会实现三色标记算法的变种以缩短 STW 的时间。三色标记算法将程序中的对象分成白色、黑色和灰色三类:
- 白色对象 — 潜在的垃圾,其内存可能会被垃圾收集器回收;
- 灰色对象 — 活跃的对象,因为存在指向白色对象的外部指针,垃圾收集器会扫描这些对象的子对象;
- 黑色对象 — 活跃的对象,包括不存在任何引用外部指针的对象以及从根对象可达的对象;
三色标记法工作原理:
- 初始状态所有对象都是白色。
- 从root根出发扫描所有根对象,将被它引用的对象标记为灰色。
- 分析灰色对象是否引用了其它对象。如果没有引用其它对象则将该灰色对象标记为黑色;如果有引用则将它变为黑色的同时将它引用的对象也变为灰色。
- 重复步骤3,直到灰色对象队列为空。此时白色对象即为垃圾对象,进行回收。
在完成三色标记后,可能用户程序在标记执行的过程中修改对象的指针,因为三色标记清除算法不支持并发和增量执行,所有需要STW。如果用户程序建立从A对象到D对象的引用,但程序中已经不存在灰色对象了,所有D对象会被垃圾收集器错误地回收。本来不应该被回收的对象被回收了,在内存管理中是非常严重的错误,这种错误称为悬挂指针,即指针没有指向特定类型的合法对象,影响内存安全性,想要并发或者增量地标记对象需要使用屏障技术。
8. 屏障技术
内存屏障技术是一种屏障指令,它可以让 CPU 或者编译器在执行内存相关操作时遵循特定的约束,目前多数的现代处理器都会乱序执行指令以最大化性能,但是该技术能够保证内存操作的顺序性,在内存屏障前执行的操作一定会先于内存屏障后执行的操作。
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
升。**
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!