知识卡片
混合写屏障
内容
(书中 Go 1.8 引入、本书按 Go 1.14 讲解)并发标记时用户协程仍在改指针,可能让黑色对象直接指向白色对象、破坏三色不变性。混合写屏障结合 Dijkstra 插入屏障(标记新写入的对象)与 Yuasa 删除屏障(标记被覆盖的旧对象),在写入或删除指针时把可能存活的对象重新标灰。它的关键收益是不再需要在标记终止阶段的 STW 里重新扫描所有协程栈,把暂停时间从毫秒级压到亚毫秒级;具体是否需要栈重扫、暂停时长属于版本实现细节。
结构图:
flowchart LR
A[用户协程写指针] --> B[写屏障触发]
B --> C[Yuasa: 标记被覆盖旧对象]
B --> D[Dijkstra: 标记新写入对象]
C --> E[保持三色不变式]
D --> E
E --> F[标记终止阶段无需重扫栈]
参考来源
- 位置:《Go语言底层原理剖析》第20章《深入垃圾回收全流程》20.6节《屏障技术》
- 结论依据:原文明确"在Go 1.8之前,尽管使用了插入屏障,但是仍然需要在标记终止期间STW阶段重新扫描根对象,来保证三色标记的一致性。为了解决重复扫描的问题,Go 1.8之后使用了混合写屏障技术,结合了Dijkstra与Yuasa两种风格",并给出混合屏障伪代码(写入时既标记旧值又标记新值),因此可以推出"混合写屏障结合插入与删除屏障、省去标记终止阶段重扫栈"的结论。
- 原始内容:在Go 1.8之前,尽管使用了插入屏障,但是仍然需要在标记终止期间STW阶段重新扫描根对象,来保证三色标记的一致性。为了解决重复扫描的问题,Go 1.8之后使用了混合写屏障技术,结合了Dijkstra与Yuasa两种风格……因此,要想在标记终止阶段不用重新扫描根对象,需要使用写屏障与删除屏障混合的屏障技术。