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