温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

golang垃圾回收中如何实现删除写屏障

发布时间:2021-12-15 10:09:21 来源:亿速云 阅读:402 作者:小新 栏目:云计算

这篇文章将为大家详细讲解有关golang垃圾回收中如何实现删除写屏障,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。

首先声明,golang 没有直接实现过删除写屏障,golang 的内存写屏障是由插入写屏障到混合写屏障过渡的。不过,虽然 golang 从来没有直接使用删除写屏障,但是混合写屏障却用到了删除写屏障的思路。

删除写屏障:也叫做基于其实快照的解决方案(snapshot-at-the-begining)。顾名思义,就是在开始 gc 之前,必须 STW ,对整个根做一次起始快照。当赋值器(业务线程)从灰色或者白色对象中删除白色指针时候,写屏障会捕捉这一行为,将这一行为通知给回收器。这样,基于起始快照的解决方案保守地将其目标对象当作存活的对象,这样就绝对不会有被误回收的对象,但是有扫描工作量浮动放大的风险。术语叫做追踪波面的回退。

删除写屏障(基于起始快照的写屏障)有一个前提条件,就是起始的时候,把整个根部扫描一遍,让所有的可达对象全都在灰色保护下(根黑,下一级在堆上的全灰),之后利用删除写屏障捕捉内存写操作,确保弱三色不变式不被破坏,就可以保证垃圾回收的正确性。

伪代码如下:

atomic Write(src, i, ref)    shade(src[i])    src[i] <- ref
 

复习一下一些概念

赋值器的颜色

  • 灰色赋值器:如果某一个赋值器尚未被回收器扫描过(即赋值器的根还没有被追踪到),或者尽管被扫描过,但是还需要重新扫描
    • golang 插入写屏障的时期,就是灰色赋值器
  • 黑色赋值器:已经被回收器扫描过,不会再对其进行扫描

插入写屏障对应的是灰色赋值器,删除写屏障对应的是黑色赋值器。

三色不变式

  • 强三色:不允许黑色对象指向白色对象
  • 弱三色:允许黑色对象指向白色对象,但必须保证一个前提,这个白色对象必须处于灰色对象的保护下

强三色不变式的框架下:要求黑色赋值器的根只能引用灰色或者黑色对象,不能引用白色对象(因为黑色赋值器不再被扫描,引用白色)。

弱三色不变式的框架下:允许黑色赋值器的根引用白色对象,但前提是白色对象必须处于灰色保护下。

获取赋值器的快照,意味着回收器需要扫描其根并将其置为黑色。我们必须在回收起始阶段完成赋值器快照的获取,并保证其不持有任何白色对象。否则一旦赋值器持有某白色对象的唯一引用并将其写入黑色对象,然后再抛弃该指针,则会违背弱三色不变式的要求。当然,为黑色对象增加写屏障可以捕捉这一内存写操作,但如此一来,该方案将退化到强三色不变式的框架下。因此,基于其实快照的解决方案将只允许黑色赋值器的存在。

删除写屏障怎么保证弱三色不变式,如下示意图:

golang垃圾回收中如何实现删除写屏障
 

 

我们看到第三张图显示,黑色指向白色没问题,只要最后 delete 指针的时候 Z 对象置灰色,那么回收的正确性就可以保证。

关于“golang垃圾回收中如何实现删除写屏障”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,使各位可以学到更多知识,如果觉得文章不错,请把它分享出去让更多的人看到。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI