面试题答案
一键面试标记阶段写屏障行为
在Go的标记阶段,写屏障(如三色标记法中的写屏障)主要作用是确保对象引用关系的变化能够被正确跟踪。当一个白色对象(未被标记的对象)被黑色对象(已被标记且其所有子对象也已被标记的对象)引用时,写屏障会将这个白色对象重新标记为灰色(已被标记但其子对象尚未全部被标记的对象)。这样做是为了防止在标记过程中,因为对象引用关系的动态变化而导致部分对象被错误地遗漏标记。例如,如果没有写屏障,在标记过程中黑色对象新引用了一个白色对象,后续可能就不会再去标记这个白色对象,造成垃圾回收错误。
清理阶段写屏障行为
在清理阶段,写屏障通常不发挥作用。清理阶段主要是回收那些在标记阶段被确定为垃圾(即没有任何可达引用的对象)的内存空间。此时不需要通过写屏障来处理对象引用关系的变化,因为标记阶段已经确定了哪些对象是存活的,哪些是垃圾。
对垃圾回收正确性的影响
- 标记阶段:写屏障通过确保对象引用关系变化能被正确跟踪,保证了所有存活对象都会被标记,避免出现悬挂指针等错误情况,大大提高了垃圾回收的正确性。如果没有写屏障,在并发环境下对象引用关系频繁变化时,可能会导致部分存活对象被误判为垃圾而被回收,破坏程序的正确性。
- 清理阶段:清理阶段写屏障不工作并不会影响垃圾回收的正确性,因为此时存活对象和垃圾对象已经在标记阶段明确区分,只需要回收垃圾对象的内存即可。
对垃圾回收性能的影响
- 标记阶段:写屏障增加了额外的开销。每次对象引用发生变化时,都需要执行写屏障的逻辑,这会增加程序的运行时间和内存开销。不过这种开销换来的是垃圾回收正确性的保证。在高并发场景下,对象引用变化频繁,写屏障的开销会相对更显著,但通过优化写屏障算法(如Go采用的混合写屏障等技术),可以在一定程度上降低这种性能损耗。
- 清理阶段:由于写屏障不工作,所以在清理阶段不存在因写屏障带来的额外性能开销,这使得清理阶段可以更高效地回收垃圾内存。清理阶段主要的性能开销在于内存的释放和整理等操作,而不需要处理对象引用关系变化所带来的额外工作。