本文转载自微信公众号「跨界架构师」,作者Zachary。转载本文请联系跨界架构师公众号。
创新互联公司-专业网站定制、快速模板网站建设、高性价比宁县网站开发、企业建站全套包干低至880元,成熟完善的模板库,直接使用。一站式宁县网站制作公司更省心,省钱,快速模板网站建设找我们,业务覆盖宁县地区。费用合理售后完善,10余年实体公司更值得信赖。
大家好,我是 Z 哥。
今天带来一篇久违的技术型文章。
之前也有不少小伙伴会问,Z 哥你好久没发技术性文章了。其实主要原因有以下几点。
第一,目前的工作偏业务以及管理,的确在技术上的精力投入不如之前那么多。这也限制了自己在纯技术性方面的知识输出。
第二,虽然自己在工作之余,也会有一部分精力专门用于技术学习,但是大多是以新技术、新框架等的了解、熟悉为主。涉及到的知识 Level 相对比较浅,就算发出来对大家的帮助也不大,就没发。
第三,从长远来看,自己也不想太把自己局限在技术的圈子里。因为在我看来,技术只是一门手艺,是吃饭的家伙,但是吃饭的家伙从来都不仅仅是技术,还有很多其它的方面。甚至其中很多事情不像具体的技术细节那样「标准化」,有很多是通过血汗积累的「非标准化」经验,我认为这些经验的价值不亚于技术知识。因此,作为有志与大家交朋友的 Z 哥,自然就不想把自己局限在「技术」这个小圈子里。
好了,回到本文的正题。最近正好在学习 Golang,对它的里面用到的三色标记法的 GC 机制有些好奇(最开始是因为名字让我联想到了三色杯冷饮~),就稍微多深入了解了一下,在这里分享出来,或许将来对你面试啥的有些帮助。
在 GC 领域里,判断对象存活的主流思路是两个,「引用计数」和「可达性分析」。
01 引用计数
顾名思义,引用计数的思路就是给每个对象进行计数,每被其它对象引用一次,计数就 +1,引用失效后,计数就 -1。当计数器的数值为 0,就意味着它没有被使用,可以回收。
02 可达性分析
可达性分析的思路就是通过引用链路判断对象是否可被触达,如果能触达说明该对象当前正在被使用,不可回收;反之,没有触达到的对象则认为是无使用的,可以回收。
这个引用链路的结构类似于有向有环图,但是根节点不止一个,是一个集合,称之为 GCRoots。
目前主流的 GC 机制大多用的是「可达性分析」这条路线。Go、Java、.Net等都是如此。为什么引用计数不好用呢?因为它有一个特别严重的问题:无法处理循环引用。
像上图这样的情况,引用计数永远不为 0,这些对象就永远不会被回收,这会严重影响回收的效果。
但是它也并不是一无是处,它的回收实时性效果更好,可以配合「可达性分析」一起使用,发挥各自的优点,在不同的场景下使用不同的策略。
由于,「可达性分析」思路是主流,所以后续发展出来的很多回收算法都以这个思路为基础的,三色标记法就是其中之一。我们今天主要来聊聊它。
在讲具体原理之前先了解一个概念,「Stop The World 」,简称「STW」。
垃圾回收器的工作流程大体如下:
第一步做标记的过程又可以分成两个步骤。
垃圾回收算法主要做的就是第一步中的第二步,三色标记法也不例外,它将从GC Roots 开始遍历的对象标记为以下三种颜色:
其实这三种颜色是啥不重要的,重要的是它们所表达的状态,灰色的中间状态,标记过程结束后只会存在白色或者黑色。
整个过程中,这些状态是如下图这样变化的。
看似很完美的解决方案,其实也存在的一个问题:标记过程中,对象引用发生了变化。
它会导致两个问题,「多标」和「漏标」。
多标就是下图这样:
由于步骤2不会STW,所以可能存在扫描过A将它标记为黑色后,又重新引用了一个原本已经被标记为白色的D(C断开了与D的引用)。此时,D就会被回收掉,导致程序出现意料之外的bug。
「漏标」就是这样:
对象 E/F/G 是“应该”被回收的。然而因为 E 已经变为灰色了,其仍会被当作存活对象继续遍历下去。最终的结果是:这部分对象仍会被标记为存活,即本轮 GC 不会回收这部分内存。
传统的解决这两个问题的思路有两个:
第一个思路专业叫法是「写屏障」,第二个是「读屏障」。其实名字就是噱头,你可以把它们俩当我们平时编程中用到的 AOP 概念来理解,在修改和读取之前做一些操作。
原始快照(Snapshot At The Beginning,SATB)。当某个时刻 的 GC Roots 确定后,当时的对象图就已经确定了。如果期间发生变化,则可以记录起来,保证标记依然按照原本的视图来。这个操作在「修改操作前」进行,JVM中 的 G1 垃圾回收器用的就是这个思路。理论上,配合 「Remembered Set」,SATB 的效率是比增量更新要高的,不过会消耗更多的内存。
基于「读屏障」的方案是:在「黑色」对象重新建立「白色」对象的引用前,将这个白色对象记录下来,避免被回收掉。这个动作在「读取操作前」进行,JVM 中的 ZGC 垃圾回收器就是这个思路。
在 Golang(1.8版本之后)里,用的是一种新的机制,称之为「混合写屏障」机制。它的思路总结下来就是4句话:
你看,其实这些原理也没那么复杂,我相信只要你搞清楚了自己面对的是什么问题,你也能想到这些方案。
好了,总结一下。
这篇呢,Z 哥和你分享了我对 Golang 中的 GC 机制「三色标记法」的了解。
GC 的底层判断对象存活思路主要是两个,引用计数和可达性分析。由于引用计数存在循环引用问题,所以大多数 GC 都是按照后者的思路实现的,Golang 也不例外。
「三色标记法」的原理是,将对象分为了三种状态:
最终将白色状态的对象回收掉。为了解决其中会存在的漏标、多标问题,它通过「混合写屏障」的机制来解决。思路是,
希望对你有所帮助。
新闻标题:聊聊Go的三色标记法
本文网址:http://www.shufengxianlan.com/qtweb/news27/480377.html
网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联