面试题答案
一键面试Go语言采用的垃圾回收(GC)算法
Go语言采用的是三色标记清除(Tri - color Mark - and - Sweep)算法。
工作原理
- 标记阶段:
- 初始状态:将所有对象标记为白色。白色代表尚未被垃圾回收器访问到的对象。
- 根对象扫描:垃圾回收器从根对象(如全局变量、栈上的变量等)开始,将所有能直接访问到的对象标记为灰色。灰色对象表示已被垃圾回收器访问到,但它引用的对象还未被完全访问。
- 灰色对象处理:垃圾回收器不断从灰色对象集合中取出对象,将其引用的对象标记为灰色,并将该灰色对象标记为黑色。黑色对象表示其本身及其引用的所有对象都已被垃圾回收器访问过。当灰色对象集合为空时,标记阶段结束。此时,白色对象即为不可达对象,会在后续被回收。
- 清除阶段:
- 垃圾回收器遍历堆内存,回收所有白色对象占用的内存空间。这些空间被重新标记为可用,供后续程序分配新对象使用。
解决内存碎片化问题
- 对象分配策略:Go语言使用了一种称为“tcmalloc”(Thread - Caching Malloc)的内存分配器。它基于线程本地缓存(Thread - Local Cache)来分配对象,减少了锁的竞争。在分配对象时,尽量将新对象分配到与之前释放对象相邻的内存位置,如果有合适的空闲空间,就直接复用这些空间,从而减少碎片化。
- 分代回收:Go语言的垃圾回收器采用了分代回收的思想(虽然不像传统分代回收那样严格区分代际)。新创建的对象通常被分配在年轻代(Young Generation),经过几次垃圾回收仍然存活的对象会被移动到年老代(Old Generation)。垃圾回收器对年轻代和年老代采用不同的回收频率和策略,优先回收年轻代中大量短生命周期的对象,减少对年老代的扫描频率,降低了碎片化的可能性。
- 紧凑机制(部分实现):虽然Go语言没有完整的内存紧凑机制,但在某些情况下,如在对象移动时(如从年轻代移动到年老代),会对内存布局进行一定程度的整理,减少碎片空间的产生。