高端网站开发案例展示,百度一下电脑版首页,上海建筑工程有限公司有哪些,杭州微网站开发公司一、这篇文章我们来聊聊Golang内存管理和垃圾回收#xff0c;主要注重基本底层原理讲解#xff0c;进一步实战待后续文章
垃圾回收#xff0c;无论是Java 还是 Golang#xff0c;基本的逻辑都是基于 标记-清理 的#xff0c;
标记是指标记可能需要回收的对象#xff0c…一、这篇文章我们来聊聊Golang内存管理和垃圾回收主要注重基本底层原理讲解进一步实战待后续文章
垃圾回收无论是Java 还是 Golang基本的逻辑都是基于 标记-清理 的
标记是指标记可能需要回收的对象那么标记的方式是什么呢
无论是Java还是Golang标记的方式的逻辑都可以表示为 “三色标记法”三色标记法用图表示的话可以看成这样 那么如果要我们以语言去表示笔者可以提供一个个人理解的表述从根对象开始以引用链的方式广度优先搜索方法将所有能够与根结点形成直接或间接引用链进行标记未标记的对象就是需要回收的对象。
什么是根对象一般来说根对象包括栈上变量和全局变量
标记其实是要占据CPU资源的或者说需要STW用户程序如果有太多的对象需要进行标记可能会导致用户程序感觉到卡顿造成服务体验卡顿。
为了降低卡顿时间目前标记的方式都是基于并发标记这样就能解决上面的问题。但是我们也知道并发可能会造成并发变量的不安全性或不一致性。
那么为了保证标记过程或者被标记对象的并发安全性或者一致性无论是Java还是Golang在标记指令前或后都会插入一个叫“屏障”的原语指令保证并发标记安全或一致性。不过Java可能采取的是写前屏障或者其他Golang采用的是“混合屏障”。
那么什么是混合屏障混合是由什么混合的呢为什么要混合
一般来说屏障可以分为“插入写屏障”和“删除写屏障”。
插入写屏障可以理解为在标记(写)对象前插入屏障(原语指令)保证一个对象标记过程不会被多个协程同时修改。但是对于栈上的变量由于屏障是一种消耗时间的行为为了保证栈快进快出的特点所以对于栈上的变量的标记是不会插入屏障的那么对于栈上的需要回收的对象需要在完成第一轮标记后对栈再进行一次标记。那么写屏障的缺点很明显就是需要二次标记单独对栈重新标记。
“删除后屏障”就是在删除一个对象引用链后插入一个屏障进行标记的行为具体删除后屏障的过程不多进行解释他的缺点就是标记精度没那么高但是不需要二次标记。
那么Golang结合“插入写屏障”和“删除后屏障”的优缺点避免二次标记和精度缺失的问题对于新对象和栈上的对象都直接标记为非回收对象即直接标记为黑色
那么标记过程我们已经清楚那么我们来说一下Golang谁来进行标记行为的。在Golang里我们一般讲的是协程所以负责标记的包含三种协程
1)默认的标记协程 2)每个处理器都有一个辅助标记协程只有处理器空闲的时候才会进行辅助标记 3)当内存不足时来申请内存的协程也会帮助标记标记数量取决于申请的
标记完成后统一放到一个叫工作池里进行垃圾对象回收。
哈哈有说的不对的地方敬请指教写文不易给俺一个点赞和收藏吧哈哈。