MST

星途 面试题库

面试题:Go垃圾回收的三色标记法在实际实现中如何与写屏障配合

在Go语言垃圾回收机制里,三色标记法是核心算法之一,而写屏障对维持标记过程的正确性至关重要。请详细阐述三色标记法与写屏障在实际实现中的配合方式,以及写屏障如何解决并发垃圾回收中的对象丢失问题。
39.5万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试

三色标记法概述

  1. 三色定义
    • 白色:未被垃圾回收器访问到的对象。在垃圾回收开始阶段,所有对象都是白色。
    • 灰色:已被垃圾回收器访问到,但它引用的对象还未全部访问的对象。
    • 黑色:已被垃圾回收器访问到,且它引用的所有对象也都已被访问的对象。
  2. 标记过程
    • 从根对象(如全局变量、栈上的变量等)开始,将所有可达对象染成灰色,放入待处理队列。
    • 从队列中取出灰色对象,将其染成黑色,并将其引用的白色对象染成灰色,重新放入队列,重复此过程,直到队列清空。此时白色对象即为不可达对象,可以回收。

写屏障在三色标记法中的作用

  1. 配合方式
    • 在并发垃圾回收场景下,应用程序和垃圾回收器同时运行。写屏障主要作用于对象引用关系发生变化的时刻。当应用程序进行写操作(修改对象引用)时,写屏障会介入。
    • 写屏障会记录对象引用的变化,确保垃圾回收器能够正确追踪对象间的可达关系。在Go语言中,写屏障采用的是插入写屏障(具体实现会有所不同,这里以插入写屏障为例说明)。
    • 当一个对象(设为A)对另一个对象(设为B)的引用关系发生改变(比如原本A不引用B,现在A引用B了),插入写屏障会将新引用的对象B染成灰色,这样就保证了在垃圾回收标记过程中,新的引用路径能够被正确追踪。
  2. 解决对象丢失问题
    • 对象丢失场景:假设在垃圾回收标记过程中,对象A(黑色)原本引用对象B(白色),在标记过程中,应用程序将A对B的引用移除,同时另一个对象C(灰色)开始引用B。如果没有写屏障,由于A已经是黑色,垃圾回收器不会再重新扫描A,而C在扫描完自己的其他白色引用对象后会被标记为黑色,此时B对象虽然实际上可达,但由于垃圾回收器的标记过程中没有扫描到B,会将B误判为不可达对象,从而造成对象丢失。
    • 写屏障解决方法:插入写屏障在对象引用关系发生变化时(如C引用B时),会将B染成灰色,这样B会被重新加入到待处理队列中,垃圾回收器后续会扫描B,从而避免了对象B被误判为不可达对象,解决了并发垃圾回收中的对象丢失问题。