GC是自动化内存管理回收机制
虚拟内存函数栈的数据是会根据函数返回而自动销毁的,而堆上的数据是不会随着函数自动销毁的,堆内数据会随着程序运行而逐渐变大,从而导致内存OOM,Go语言就用了GC来清理堆上的内存数据。
堆上内存数据不在被栈上和数据段上的引用变量所指向,那就一定 是内存垃圾。这个原理称为"可达性",近似等价于”存活性“
引用计数reference counting:php的GC,每个对象都有一个被引用的计数器,每被引用一次则被引用对象计数器+1,当引用对象失效,则被引用对象计数器-1,当计数器是0时,可回收
标记-清除Mark and Sweep(非移动式垃圾回收):每次启动垃圾回收都会暂停当前所有的正常代码执行,运行一个扫描线程重新运行系统获得链路,通过链路判断对象是否可被触达,如果能触发说明对象当前正在被使用,不可回收;反之,没有触达到的对象则认为无用,可以回收。
因为GC是清理堆上的数据,那么链路分为2种:
- 栈到堆
- 数据段到堆
三色标记法:是mark and sweep的优化版,go语言用的此方法
标记-整理 Mark and Compact(移动式垃圾回收):原理和标记清除Mark and Sweep是一样的链路可达性。Mark and Compact会在清理完堆上的内存后将内存重新整合到一起,避免内存碎片过多。可是整理肯定会涉及到内存的迁移和栈上数据的重新指向
复制式移动法(移动式垃圾回收):他同Mark and Compact算法,他会将堆内存上分成2个一样大小的内存区间(from,to)。原来存在from空间的数据,被GC清理后剩余的内存全部存到to空间,from内存清空,避免内存碎片过多。他也是会涉及到内存的迁移和栈上数据的重新指向,并且堆内存只有一半的使用率
分带回收:这里不一一介绍了
移动式垃圾回收 及 会移动堆内存空间,避免内存碎片过多
非移动式垃圾回收 及 不会移动堆内存空间,会有很多内存碎片,产生内存浪费
三种颜色的作用:
三色标记法步骤:
根据时间片段,有多种方式:
STW,stop the world;让程序暂停,GC扫描标记标记GCROOTS的对象引用。会阻塞进程,让系统有卡顿现象。
将STW切割成多个时间段,让垃圾回收和程序并发执行(交替执行)。但是这个会引起新的问题,就是前一个时间段的GC将节点标记成了黑色,切换到程序后被变量赋值,重新指向了白色,导致下一个时间片的GC把白色节点的内存释放导致OOM。
黑指向白的实例:
- GC段1:将一个切片变量a被标记成黑色,栈和堆上都是黑色(切片是引用变量所以存在数据结构堆内,栈存着指针)
- 切换到业务程序:创建了一个切片变量b(GC默认节点都是白色,所以此时b的堆栈都是白色节点),切片变量a的pointer被重新赋值指向切片b的七层数组。此时变量a的栈是黑色,堆是白色

不允许黑色节点指向白色对象,在业务程序修改操作时,创建读/写屏障:

所有被黑色对象引用的白色对象都处于灰色保护状态.
一个线程进行GC,其他线程进行业务代码的运行。
考虑点:
多个线程同一个时间段进行回收。
考虑点:
在某些特定情况下,仍然需要使用Stop-The-World(STW)来保证线程安全。以下是一些可能需要使用STW的情况:
巨人肩膀
https://blog.csdn.net/weixin_42322309/article/details/106915910?spm=1001.2014.3001.5502
https://www.bilibili.com/video/BV1n5411H7qS/?spm_id_from=333.999.0.0&vd_source=6e9548d830b147140ad59cd8010b6e7b