并发标记与并发清除是标记-清除算法摆脱全量停顿的关键演进,通过写屏障保障一致性、分阶段增量标记、位图索引与堆分区并行清除等技术大幅压缩stw时间。

并发标记与并发清除,是标记-清除算法摆脱“全量停顿”困局的关键演进路径。核心目标很明确:把原本必须 Stop-The-World 的长耗时阶段,拆解、并行化、或移入应用线程运行间隙,从而大幅压缩 STW 时间,提升系统响应性。
为什么传统标记-清除需要长时间停顿
原始标记-清除算法在标记阶段必须暂停所有用户线程,否则引用关系动态变化会导致漏标或误标;清除阶段虽可异步,但若堆很大,线性扫描仍可能引发可观延迟。两者叠加,GB级堆容易出现百毫秒甚至秒级停顿,对实时服务不可接受。
并发标记:靠写屏障维持一致性
让标记与用户线程同时跑,关键在于拦截对象引用的变更。主流方案依赖写屏障(Write Barrier):
- Dijkstra插入屏障:当黑色对象新增指向白色对象的引用时,立即将该白色对象标记为灰色,防止漏标
- 混合写屏障(Go 1.8+):同时处理插入和删除场景,初始栈仅扫描一次,避免重新扫描开销
- 增量式分阶段:如方舟运行时将标记划分为128个粒度,每轮只处理一小片,主动 yield CPU,把单次 STW 控制在亚毫秒级
并发清除:从串行遍历转向并行分区
清除阶段不再逐字节扫描整个堆,而是利用内存布局特征提升效率:
- 位图索引清扫:用紧凑位图记录每个内存块是否存活,支持按块并行判断与释放
- 堆分区并行处理:将堆切分为固定数量区块(如64块),多线程各自清扫,吞吐量可提升数倍
- 延迟清扫(Lazy Sweep):不立即回收,而是在后续内存分配时按需清理空闲块,进一步摊薄延迟
协同优化:不能只盯单个阶段
并发标记与并发清除不是孤立改进。实际工程中需配合其他机制才能发挥最大效果:
- 标记阶段 CPU 占用过高时,需引入自适应调度,限制 GC 线程资源配额
- 清除后碎片率上升,需搭配内存整理策略(如部分压缩)或分代设计缓解
- 写屏障本身有开销,高频写场景下需权衡精度与性能,例如采用采样式屏障或硬件辅助











