Shenandoah并发压缩通过读屏障+写屏障+转发指针(非Brooks Pointers)协同实现变量无感迁移:对象迁移时,读写操作均自动重定向至最新副本,仅初始和最终标记需极短STW。

Shenandoah 并发压缩算法不靠“避免读写冲突”来保证一致性,而是通过读屏障 + 写屏障 + Brooks Pointers 的协同设计,让读和写在对象迁移过程中天然兼容——冲突不是被拦截或排队,而是被语义重定义为“始终访问逻辑对象最新副本”。
读操作:靠读屏障自动跳转,不依赖引用是否更新
当应用线程通过任意旧地址(栈变量、寄存器、堆中字段)访问对象时,JVM 在每次字段读取前插入读屏障:
- 检查该对象头的 Brooks Pointer:若仍指向自身,直接读取原位置
- 若已 CAS 更新为新地址,则 CPU 立即跳转,后续所有字段加载都落在 to-region 的新副本上
- 即使多个线程同时读同一旧地址,因 Brooks Pointer 是原子更新,不会出现“半迁移”状态
写操作:写屏障确保所有修改都落到最新副本
写操作同样受控,并非直接写入旧地址:
- 写屏障在字段赋值前触发,先确认对象是否已转发;若已转发,自动将写入目标重定向至新副本
- 若对象尚未迁移(Brooks Pointer 仍指自身),写入原位置,GC 后续复制时会包含最新值
- 写屏障还参与维护转发一致性:比如在复制完成但 Brooks Pointer 尚未更新的极短窗口,它可阻塞写入或触发重试,确保不丢失更新
并发迁移中的“冲突”本质是访问时序问题,Shenandoah 不序列化,而用原子切换兜底
传统 GC 必须 STW 来禁止“读旧地址 + 写新地址”的竞态;Shenandoah 把这个难题转化为一个确定性状态机:
- Brooks Pointer 只有两个合法状态:“未转发”(指向自己)或“已转发”(指向 to-region)——无中间态
- 读/写屏障均基于该字段做分支判断,行为完全一致且无锁
- GC 线程只负责复制 + 原子更新指针;应用线程永远按当前指针状态执行,无需协调、无需等待
实际边界与保障点
这套机制不追求零开销,但能消除 STW 依赖:
- 读写屏障带来微小延迟(现代 CPU 分支预测下约 1–2 纳秒),但换来了初始/最终标记外全程无停顿
- 所有旧引用(包括 JIT 编译后内联的栈局部变量)无需刷新,靠屏障实时路由
- 写屏障还辅助处理弱引用、JNI 引用等特殊路径,确保跨语言访问也同步到新副本

















