Go面试看这里了~(二十九)

161 篇文章 12 订阅

原文地址:Go面试看这里了~(二十九)

1、常见垃圾回收机制?

常见垃圾回收机制一:引用计数。

意思是对每个对象维护一个引用计数,当引用对象的对象被销毁时,引用计数减去1,如引用计数为0则进行垃圾回收,此方式的优点是对象可以很快被回收,不会出现内存耗尽或达到阀值时才回收的情况,缺点是不能很好的处理循环引用,且实时维护引用计数也有一定的代价,在Python、PHP、Swift中有使用。

常见垃圾回收机制二:标记-清除。

从根变量开始遍历所有引用的对象,引用的对象标记为【被引用】,没有被标记的进行回收,优点是解决了引用计数的缺点,缺点是需STW,也就是要暂时停掉程序运行,例子就是Golang采用的三色标记法。

常见垃圾回收机制三:分代收集。

按对象生命周期长短划分不同的代空间,生命周期长的放入老年代,短的放入新生代,不同代有不同的回收算法和回收频率,优点是回收性能好,缺点是算法复杂,JAVA中有体现。

2、GC垃圾回收机制?

Go通过gcmarkBits位图标记span的块是否被引用,对应内存分配中的bitmap区,来看图片感受下:

三色标记含义:

  1. 灰色:对象已被标记,但该对象包含的子对象未标记。

  2. 黑色:对象已被标记,且该对象包含的子对象也已标记,gcmarkBits对应的位为1(该对象不会在本次GC中被清理)。

  3. 白色:对象未被标记,gcmarkBits对应的位为0(该对象本次GC将被清理)。

举个栗子,当前内存中有A~F一共6个对象,根对象a、b本身为栈上分配的局部变量,根对象a、b分别引用了对象A、B, 而B对象又引用了对象D,则GC开始前各对象的状态如下图所示:

可看到初始状态下所有对象都是白色的,接着开始扫描根对象a、b,由于根对象引用了对象A、B,那么A、B变为灰色对象,接下来就开始分析灰色对象,分析A时,A没有引用其它对象,所以很快就转入黑色,B引用了D,则B转入黑色的同时还需要将D转为灰色,接下来灰色对象只有D,由于D没有引用其它对象,所以D转入黑色,标记过程到此结束,最后黑色的对象会被保留下来,白色对象会被回收掉。

3、GC触发的方式?

  1. 阈值:默认内存扩大一倍,启动gc。

  2. 定期:默认2min触发一次gc,src/runtime/proc.go:forcegcperiod。

  3. 手动:runtime.gc()。

4、STW(stop the world)?

是GC最大的性能问题,对于GC而言,需要停止所有内存变化,也就是停止所有goroutine,等待gc结束之后才恢复,标记-清除(mark and sweep)算法的STW(stop the world)操作,就是runtime把所有线程全部冻结,意味着此时用户逻辑是暂停的,如此所有的对象都不会被修改,此时去扫描是绝对安全的。

标记-清除(mark and sweep)算法包含两部分逻辑,标记和清除,Go三色标记法中最后只剩下的黑白两种对象,黑色对象是程序恢复后接着使用的对象,如不碰黑色对象,只清除白色对象,就不会影响程序逻辑,所以清除操作和用户逻辑可以并发,标记操作和用户逻辑也是并发的。

5、GC操作流程?

  1. Sweep Termination:对未清扫的span进行清扫,只有上一轮GC清扫工作完成才可开始新一轮的GC。

  2. Mark:扫描所有根对象及根对象可以到达的所有对象,标记其不被回收。

  3. Mark Termination:完成标记工作,重新扫描部分根对象(要求STW)。

  4. Sweep:按标记结果清扫span。

整个GC流程会进行两次STW(Stop The World),第一次是Mark阶段的开始,此时STW会准备根对象的扫描,启动写屏障(Write Barrier)和辅助GC(mutator assist),第二次是Mark Termination阶段,此时STW会重新扫描部分根对象,禁用写屏障(Write Barrier)和辅助GC(mutator assist)。

要注意的事,不是所有根对象的扫描都需要STW,如扫描栈上的对象只需停止拥有该栈的G,从go 1.9开始,写屏障的实现使用了Hybrid Write Barrier,大幅减少了第二次STW的时间。

6、并行GC失败操作流程?

因为Go支持并行GC,也就是支持GC扫描和Go程序同时运行,带来的问题是GC描的过程中Go程序可能改变对象的依赖树,如GC扫描时发现根对象A和B,B拥有C的指针,此时GC先扫描A,A无对其它对象的引用,所以GC将A放入黑色,之后Go程序操作B将C的指针交给A,再往后GC扫描B时,B无对其它对象的引用,所以GC将B放入黑色,但现在C在白色,所以会被回收,但A确实引用C。

7、GC写屏障(Write Barrier)?

Go在GC标记阶段会启用写屏障,启用后操作流程如下:

  1. GC先扫描A,A放入黑色。

  2. B把C的指针交给A。

  3. 由于A在黑色,所以C放入灰色。

  4. C没有子对象,放入黑色。

  5. 扫描B,B没有子对象,放入黑色。

即使A在稍后丢掉C,下一轮GC也会回收C,开启写屏障后,当指针发生改变,GC会认为在这一轮扫描中该指针是存活的,所以会放入灰色。

至此,本次分享就结束了,后期会慢慢补充。

以上仅为个人观点,不一定准确,能帮到各位那是最好的。

好啦,到这里本文就结束了,喜欢的话就来个三连击吧。

扫码关注公众号,获取更多优质内容。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

luyaran

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值