Java 中的 CMS 和 G1 垃圾收集器如何维持并发的正确性?

Java 中的 CMS 和 G1 垃圾收集器如何维持并发的正确性?

CMS(Concurrent Mark-Sweep)和 G1(Garbage-First)垃圾收集器是两种低延迟的垃圾回收器,它们通过并发阶段与应用线程(Mutator)同时运行,以减少暂停时间。为了维持并发垃圾回收的正确性,二者采取了不同的技术和策略。


1. CMS 垃圾收集器的并发正确性维护

1.1 基本工作原理

CMS 使用“标记-清除”算法,主要阶段包括:

  1. 初始标记(STW):标记 GC Roots。
  2. 并发标记:从 GC Roots 开始,遍历对象图,标记所有可达对象。
  3. 重新标记(STW):处理并发标记过程中新产生的引用变化。
  4. 并发清理:清理未标记的垃圾对象。

1.2 并发正确性维护方法

  • 写屏障(Write Barrier)

    • 在 Mutator 修改引用关系时,记录修改到一个“卡表”(Card Table)或“脏卡”列表。
    • 确保并发标记阶段的新引用可以被重新标记阶段捕获。
  • 增量更新(Incremental Update)

    • Mutator 在标记阶段修改了指向未标记对象的引用,CMS 会将新创建的引用加入到待标记队列。
  • Stop-The-World 重新标记

    • 通过短暂停顿扫描卡表中的脏卡,捕获并发标记期间可能遗漏的引用变化,确保标记阶段的准确性。

2. G1 垃圾收集器的并发正确性维护

2.1 基本工作原理

G1 使用“标记-整理”算法,将堆分为多个固定大小的分区(Region),垃圾回收按分区优先级进行。主要阶段包括:

  1. 初始标记(STW):标记 GC Roots。
  2. 并发标记:从 GC Roots 遍历对象图,标记可达对象。
  3. 最终标记(STW):处理并发标记阶段的引用变化。
  4. 清理与整理:回收垃圾对象,并压缩分区。

2.2 并发正确性维护方法

  • SATB(Snapshot-At-The-Beginning)

    • G1 使用 SATB 技术维持并发标记的正确性。
    • 在标记开始时,记录 Mutator 的对象状态快照,而不是跟踪所有引用的变化。
    • Mutator 如果删除了对象的引用,被删除的对象仍会被视为可达,从而保证并发标记阶段不遗漏。
  • 写屏障(Write Barrier)

    • 在对象的引用发生变化时,通过写屏障将旧引用添加到 SATB 的缓冲区中。
    • 确保即使 Mutator 修改了对象图,回收器仍能完整标记。
  • 最终标记(Final Remark)

    • 在并发标记结束后,通过短暂停顿处理 SATB 缓冲区中的变更记录,确保标记结果一致。

3. CMS 和 G1 在并发正确性上的比较

特性 CMS G1
算法 标记-清除 标记-整理
引用变化的处理 增量更新(Incremental Update) 快照集(SATB)
写屏障 修改引用时记录脏卡 修改引用时记录旧引用
额外的 STW 停顿 重新标记阶段 最终标记阶段
并发标记的正确性保障 卡表记录脏区域,重新扫描 SATB 缓冲区记录引用变化
实现复杂性 相对较低 较高

4. 总结

  • CMS通过增量更新和卡表记录引用变化,使用重新标记阶段来确保并发标记的正确性。它更简单,但会有内存碎片和“Concurrent Mode Failure”问题。
  • G1通过 SATB 快照机制记录标记起点的状态,结合最终标记阶段的补充处理,确保并发标记的准确性。G1 的实现更复杂,但其分区化设计和整理过程能够有效减少内存碎片,适合大堆和低延迟场景。
posted @   Eiffelzero  阅读(50)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
历史上的今天:
2022-12-11 1827. 最少操作使数组递增
点击右上角即可分享
微信分享提示