CMS的“并发清除”是将标记-清除算法中原本需STW的清除阶段改为与用户线程同时执行,以实现低延迟目标;它依赖写屏障与卡表保障安全性,并通过预留空间应对浮动垃圾,本质是调度层面的工程优化而非算法逻辑改变。

CMS 的“并发清除”不是对标记-清除算法本身的算法逻辑改进,而是对执行方式的关键创新——它把原本必须全程 STW(Stop-The-World)的“清除”阶段,改为与用户线程**同时运行**,从而大幅压缩整体停顿时间。
为什么清除阶段必须并发?
CMS 的核心目标是低延迟,而标记-清除算法本身不移动对象、不压缩内存。如果在清除阶段仍要求 STW,就必须暂停所有应用线程,逐个扫描并回收已标记为垃圾的对象——这会带来可观的停顿,违背设计初衷。因此,并发清除的本质是:**用系统资源(CPU、内存带宽)换时间,允许 GC 线程和业务线程共享处理器,在应用继续运行的同时清理空间。**
并发清除如何安全执行?
它依赖两个关键保障机制:
- 写屏障(Write Barrier)配合卡表(Card Table):当用户线程修改老年代对象引用时,JVM 会记录该操作所在的内存页(卡页)为“脏”。并发清除阶段只需关注这些脏页中可能新产生的引用关系,避免漏标或误删;
- 预留空间策略:由于清除过程中用户线程仍在分配对象(产生“浮动垃圾”),CMS 必须提前预留一部分老年代空间(通过 -XX:CMSInitiatingOccupancyFraction 控制触发阈值),确保有足够缓冲容纳新对象,防止因空间不足触发 Concurrent Mode Failure。
并发清除带来的代价
这种并发性并非零成本:
- GC 线程持续占用 CPU 资源,降低整体吞吐量;
- 无法处理清除期间新产生的垃圾(即浮动垃圾),需等待下次 GC;
- 清除后不整理内存,长期运行易导致碎片化,可能因无法分配大对象而被迫触发 Full GC(此时启用 SerialOld 后备收集器,STW 时间显著增加)。
它和“算法改进”有什么区别?
标记-清除的算法逻辑没变:仍是“标记存活 → 清除未标记”。CMS 没改变这个两步范式,也没引入压缩或复制。它的突破在于**调度层面**——把“清除”从串行、阻塞操作,变成可预测、可控、与业务共存的后台任务。这是工程权衡的结果:牺牲部分吞吐和内存连续性,换取响应时间的确定性。


















