Golang 程序运行的时候,内存中的对象可以标记为三色:白色、灰色、黑色。
想象你是一个保洁阿姨(GC),你的任务是把房间里没人要的垃圾扔掉,但最麻烦的是:你干活的时候,屋子里的人(程序)还在不断地扔东西、搬东西。
为了不扔错东西,你准备了三个颜色的塑料袋:
第一步:准备阶段(发袋子)
- 白色袋子:屋里所有的东西,默认先全部装进白色袋子(全是潜在垃圾)。
- 灰色袋子:你先把那些大家手里正攥着的、桌面上摆着的(根对象:栈、全局变量)东西,换成灰色袋子。
第二步:标记阶段(翻找关联)
这一步最关键,你要开始“顺藤摸瓜”:
- 你从灰色袋子里拿出一个东西看一眼。
- 如果这个东西关联了其他白色袋里的东西(比如一个本子里夹着一张发票),你就把那张发票也换成灰色袋子。
- 等这个东西关联的所有活物都找齐了,你就把手里这个东西换成黑色袋子(表示这玩意儿彻底安全了,检查过了)。
重点来了(写屏障):
在你翻找的时候,如果有人新买了个东西,或者把东西递给了别人,他必须大喊一声:“阿姨,这东西我要用!” 然后你无脑直接给它套个灰色袋子。这样就不会出现“你以为是垃圾,其实人家刚要用”的情况。
第三步:清理阶段(扔垃圾)
等所有的灰色袋子都变成了黑色袋子(说明能找着的活物都找完了),剩下的事儿就简单了:
- 黑色袋子:全是宝贝,撕掉袋子留着。
- 白色袋子:全是没人要的垃圾,统统扔进垃圾车!
总结一下这三色:
- 白色:还没检查到的,或者是检查完了发现没人要的(倒霉蛋)。
- 灰色:确定要留着,但还没看它下面还牵扯到谁(排队中)。
- 黑色:确定要留着,而且它引用的东西也都找齐了(安全区)。
为什么不直接“一刀切”暂停程序?
因为如果房子太大,阿姨打扫时让全家人都原地不动(STW),大家会疯掉的(程序卡顿)。
通过这三色袋子和“新买东西必须套灰袋”的规矩,阿姨可以边打扫边让大家活动。虽然中间会短暂让大家停一下手头工作(STW 开启/关闭屏障),但绝大部分时间大家都在各忙各的。