GC介绍:
GO创建对象会给他分配内存资源,如果这个对象不使用了,而这个内存资源却一直被占用的话,那么我们的电脑很快就会被放满,所以需要将这些垃圾对象进行回收。
什么才是垃圾 : 要回收,那么我们必须知道什么才是垃圾,什么不是垃圾。在我们看来,一个对象以后都不用了,就是垃圾。在程序看来,一个对象没有被引用了,就是垃圾。
GC的流程:
首先说明一下,下面说的停,都是STW,stop the world,全世界暂停,所有运行的都停下来了。
第一个过程: 先告诉所有人,停一下,我来记录一下当前状态
第二个过程: 告诉所有人,你们继续,该干嘛干嘛,我标记一下要用的对象
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/acb58e5667ba88c2e090fe38b858f936.jpeg)
一开始所有点是白色,首先从根节点出发,标记相连的点为灰色(相连证明有引用),并且将所有灰色的点存起来;
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/e7e14ad05711cf190babd0e120f4d1d6.jpeg)
然后遍历所有灰色的点,标记所有灰色的点相连的点为灰色,并且将自己标记为黑色;然后重复,直到没有点是灰色;
第三个过程: 告诉所有人,再停一下,然后清除所有白色的点,因为白色的点是没人引用的,也就是垃圾。
分析: 为什么要暂停两次?为什么不直接标记?因为如果再标记的过程中不断的在创建新的对象,那么永远就标记不完了。如果标记的过程中,原来的被标记的对象引用发生变更也会导致问题。那么既然会导致那么多问题,为什么不直接停下来,标记完回收完了再开始呢? 因为慢。所以这样GC的原因是既要保证GC正常执行,又要保证效率,不能停的时间太长。
第一个过程:其实第一次停的时候,启动了一个写屏障 (write barrier)它需要记录后续过程中新创建的对象。对于和用户程序并发运行的垃圾回收算法,用户程序会一直修改内存,所以需要记录下来。在扫描对象的时候可能会有新的对象分配,这个时候就需要通过写屏障(write barrier)记录下来。
第二个过程:这个过程称为三色标记,有点类似广度优先搜索。
第三个过程: 这次是必须停,真正要去清除那些垃圾了。
GC总结: 三色标记法:
- 起初所有对象都是白色。
- 从根出发扫描所有可达对象,标记为灰色,放入待处理队列。
- 从队列取出灰色对象,将其引用对象标记为灰色放入队列,自身标记为黑色。
- 重复 3,直到灰色对象队列为空。此时白色对象即为垃圾,进行回收。
GC的触发条件
那毕竟GC还是需要STW的,虽然可能停止时间很短,但是对于程序来说,整个程序停止1秒那对于用户来说就是致命打击。所以GC肯定需要一个触发的条件,不能想来就来。
-
GC百分比
这是一个触发的条件,默认GC百分比设置的是100,意思是,如果这次回收之后总共占用2M的内存,那么下次触发的条件时当超过4M的时候;同理,当这次回收之后总共占用4M,那么下次触发条件就是8M。 -
2分钟
这个简单,当一定时间(2分钟)没有执行过GC就触发GC -
手动
使用命令runtime.GC()手动触发GC