JVM 锁 bug 导致 G1 GC 挂起问题分析和解决
编者按:笔者在 AArch64 中遇到一个 G1 GC 挂起,CPU 利用率高达 300%的案例。经过分析发现问题是由 JVM 的锁机制导致,该问题根因是并发编程中没有正确理解内存序导致。本文着重介绍 JVM 中 Monitor 的基本原理,同时演示了在什么情况下会触发该问题。希望通过本文的分析,读者能够了解到内存序对性能、正确性的影响,在并发编程时更加仔细。 现象 本案例是一个典型的弱内存模型案例,大致的现象就是 AArch64 平台上,业务挂死,而进程占用 CPU 持续维持在 300%。配合 top 和 gdb,可以看到是 3 个 GC 线程在 offer_termination 处陷入了死循环: 多个并行 GC 线程在 Minor GC 结束时调用 offer_termination,在 offer_termination 中自旋等待其他并行 GC 线程到达该位置,才说明 GC 任务完成,可以终止。(关于并行任务的中止协议问题,可以参考相关论文,这里不做着重介绍。 简单地说,在并行任务执行时,多个任务之间可能存在任务不均衡,所以 JVM 内部设计了任务均衡机制,同时必须设计任务终...