Go GC的基本特征是“非分代、非紧缩、写屏障、并发标记清理”
GC 阶段:
三色标记和写屏障
- 起初所有对象都是白色。
- 扫描找出所有可达对象,标记为灰色,放入待处理队列。
- 从队列提取灰色对象,将其引用对象标记为灰色放入队列,自身标记为黑色。
- 写屏障监视对象内存修改,重新标色或放回队列。
辅助标记作用?
-
主要解决了垃圾回收正常结束和循环的问题。
-
问题:在并发标记阶段,扫描内存的同时,用户协程也不断被分配内存,当用户协程内存分配速度快到后台标记协程来不及扫描时,GC标记阶段将永远不会结束,从而造成内存泄漏。因此引入了辅助标记算法。
-
解决方法:当go发现用户协程被分配了超过限度的内存而不得不将其暂停并切换到辅助标记工作。所以让后台标记协程需要扫描的内存等于新分配的内存,在并发标记阶段,一旦新分配内存M,就必须完成M的扫描工作。
屏障技术
-
主要解决了准确性的问题
-
问题:假设垃圾回收已经扫描完成根对象a(为黑色)并继续扫描期间。白色对象z被灰色对象y引用。但此时工作协程让黑色的根对象a指向白色对象z,由于黑色对象不会被扫描。这将导致白色对象z被视为垃圾被回收。.
-
强三色不变性:指所有的白色对象都不能被黑色对象引用。上面的白色对象z不能被根对象引用
-
弱三色不变性:允许白色对象被黑色对象引用。但是白色对象必须有一条路径是被灰色对象引用的。 为了维持在并发标记写入和删除对象时的三色性不变,引入屏障技术。
-
解决方法:在写入或删除对象时 将可能活着的对象标记为灰色。即将上面的白色对象z标记为灰色对象。
在并发标记写入时屏障:
在将白色对象z写入根对象,将其标记为灰色对象。这样对象z就会被扫描
在并发标记删除时屏障:
删除对象z时,会把对象z标记为灰色。这样对象z就会被扫描
插入屏障与删除屏障通过在写入和删除时重新标记颜色保证了三色不变性,解决了并发标记期间的准确性问题,但是它们都存在浮动垃圾的问题