并发标记
2025年2月13日大约 2 分钟
并发标记
并发标记是说:用户线程和 GC 线程同时进行的阶段。主要在 CMS 和 G1 中有这个阶段,为了减少 STW 的停顿时间。但是又会引入一些其它问题!
对象消失问题
- 对象消失也就是漏标问题(存活对象没有被标记)这个错误是致命错误,不能被忍受的。主要原因是因为破坏了三色标记算法的原则。即:黑对象不能直接引用白对象,和所有白对象的被引用链必须包含至少一个灰对象。
上述第一点:是说一个黑对象在并发标记阶段又新增了一个引用(白对象)但是黑对象是被扫描过的,不能再被扫描了。
// 初始状态:A(黑) -> B(白) // 应用线程执行: A.field = C; // 新增引用:A(黑) -> C(白) B = null; // 删除引用:A -> B 断开 // C漏标
上述第二点:是说灰对象断开了对白对象的引用,导致白对象无法被扫描。
// 初始状态:A(灰) -> B(白) -> C(白) // 应用线程执行: A.field = null; // 删除引用:A -> B 断开 D.field = B; // 新增引用:D(黑) -> B(白) // B,C 漏标
- 三色标记是专门用于并发标记阶段,用于标记对象的存活状态算法,其中分成黑(对象已标记且所有引用也被标记)、灰(自己至少有一个引用未被标记)、白(未被标记)三种状态。
- 如何解决? 在 CMS 和 G1 中提供了不同的解决方案。CMS 中采用增量更新,G1 中采用原始快照解决这个问题。
- 增量更新:记录新增的黑对白的引用,在后面重新扫描。也就是 CMS 的重新标记阶段。
- 原始快照:记录此时堆中所有存活对象的引用关系(形成初始快照,在初始标记阶段),然后记录被删的灰到白的引用。然后重新标记这些被删除引入的对象及其可达对象。,保证初始快照中存活的对象仍存活。G1 的最终标记阶段。
浮动垃圾问题
浮动垃圾是:原本已经被标记存活的对象,在后面继续并发标记时,这个对象的引用又消失了,但是我们已经把它标记成存活了,所以无法回头了。这个问题我们是可以容忍的,毕竟下次 GC 时就会被回收了。