
一、先看场景(核心案例)假设并发标记刚开始时,对象图是这样的:GC Roots → A → B ↘ C并发标记期间,应用线程执行了两步操作:// 步骤1:切断A对B的引用A.next=null;// 步骤2:让C引用BC.next=B;最终对象图变成了:GC Roots → A (不再指向B) ↘ C → B (C现在指向B)问题来了:B应该存活吗?答案:应该存活!因为C最终引用了B。但GC的并发标记已经在进行中,怎么保证B不被误回收?SATB和增量更新用了完全不同的策略。二、SATB写屏障(G1用的方式)核心策略:“宁可错杀一千,不可放过一个”——记录旧引用// G1在每次字段赋值前插入的代码(SATB写屏障)voidsatb_write_barrier(Objectobj,Objectold_value,Objectnew_value){// 把即将被覆盖的旧引用记录下来if(old_value!=nullis_white(old_value)){satb_queue