​Garbage Collection​​GC​​GC​​GC​​GC​

Go V1.13之前的标记-清除(mark and sweep)算法

一、暂停程序业务逻辑,分类出可达和不可达对象,然后做上标记

Go的内存回收机制(三色屏障)_java

二、清除所有未标记的对象

Go的内存回收机制(三色屏障)_java_02

​mark and sweep​​STW(stop the world)​
​STW​​CPU​
​process​

但是缺点也很明显

​heap​​heap​
​sweep​

不过仍然无法避免上面的缺点.

Go V1.5的三色标记法

​GC​​goroutine​​STW​

算法过程中三色分别是白表,灰表,黑表

Ⅰ.程序创建初,把所有对象标记未白色放入白表中

Go的内存回收机制(三色屏障)_垃圾回收_03

​GC​

Go的内存回收机制(三色屏障)_json_04

Ⅲ.遍历灰色集合,将灰色对象引用的对象从白色集合放入灰色集合,然后把自己放入灰色集合

Go的内存回收机制(三色屏障)_垃圾回收_05

Ⅳ.不断重复第三步,直到没有灰色节点,此时白表中的对象就是垃圾,可以被回收.

​bfs​
​GC​​STW​
​STW​

Go的内存回收机制(三色屏障)_restful_06

此时[对象2]去掉对[对象3]的引用,同时[对象4]加上对[对象3]的引用

那么对象3仍然不会是垃圾,然而此时灰色节点已经到不了对象3了,对象3最后会成为垃圾被错误回收

Go的内存回收机制(三色屏障)_java_07

所以在三色标记法中,会出现错误的原因有两个

  • 条件1: 一个白色对象被黑色对象引用
  • 条件2: 一个白色对象和灰色对象的可达关系遭到破坏
​STW​

三色标记的屏障机制

强三色不变式

实质上是强制的不允许黑色对象引用白色对象, 这样就不会出现白色对象被误删的情况

插入屏障

在A对象引用B对象时,B对象被标记未灰色.

此时满足强三色不变式(不存在黑色对象引用白色对象的情况,因为白色会强制变为灰色)

插入屏障是一个很耗费性能的行为,而栈需要更高的性能要求,因此,插入屏障技术只运用在堆内存空间里,不会运用到栈里。

​STW​​STW​

弱三色不变式

允许黑色对象引用白色对象时, 但需要满足条件

只有当这个白色对象存在其他灰色对象对它的引用,或它的可达链路上存在灰色对象时

删除屏障

被删除的对象,如果自身为灰色或者白色,那么就会被标记为灰色。

当然,这种方式的回收精度比较低,可能那个被删除的对象本身就是个垃圾,但是我们仍然把它在这一轮变成灰色, 无法回收。

混合写屏障规则

​GC​
​GC​

③.被删除的对象标记为灰色

④.被添加的对象标记为灰色

这里注意,屏障技术是不在栈上应用的,因为要保证栈的运行效率