我正在尝试更深入地研究 golang 并开始研究 golang GC 实现。
我已经阅读了文章并尝试理解它。
让我们看一下文章的推理部分。
我将引用其中的一些文字以便快速访问,并提供一些图片以便更好地理解我不理解的内容。
所以我们有混合写屏障:
writePointer(slot, ptr):
shade(*slot)
if current stack is grey:
shade(ptr)
*slot = ptr
在混合屏障中,两种阴影和条件共同作用以防止变异器隐藏对象:
- shade(*slot) 通过将指向对象的唯一指针从堆移动到堆栈来防止变元隐藏对象。如果它尝试从堆中取消对象的链接,这将使其着色。
- shade(ptr) 通过将指向对象的唯一指针从堆栈移动到堆中的黑色对象来防止变元隐藏该对象。如果它尝试将指针安装到黑色物体中,则会遮蔽它。
- 一旦 goroutine 的堆栈为黑色,则阴影(ptr)就变得不必要了。 Shadow(ptr) 通过将对象从堆栈移动到堆来防止隐藏对象,但这需要首先在堆栈上隐藏一个指针。扫描堆栈后,它仅指向着色对象,因此它不会隐藏任何内容,并且阴影(*槽)会阻止它隐藏堆栈上的任何其他指针。
这三点对我来说似乎很清楚。
来自基本原理部分:
混合屏障的优点在于,它可以让堆栈扫描永久变黑堆栈(没有 STW,也没有对堆栈的写屏障),这完全消除了堆栈重新扫描的需要,进而消除了对堆栈屏障的需要并重新扫描列表。
假设这样我无法理解GC如何处理以下情况:
我错过了什么?
在此设计中,扫描堆栈会在扫描活动帧时短暂暂停 goroutine
您提到的情况实际上并不存在。堆栈颜色的变化是原子的