Go语言学习
  • README
  • Go 基础
    • go语言介绍
    • go语言主要特性
    • go内置类型和函数
    • init函数和main函数
    • 下划线
    • iota
    • 字符串
    • 数据类型:数组与切片
    • 数据类型:byte、rune与字符串
    • 变量的5种创建方式
    • 数据类型:字典
    • 指针
    • 数据类型:指针
    • 类型断言
    • 流程控制:defer延迟执行
    • 异常机制:panic和recover
    • 函数
    • go依赖管理
    • go中值传递、引用传递、指针传递区别
  • 标准库
    • Go net/http包
  • 数据结构
    • 哈希表
      • 为什么对 map 的 key 或 value 进行取址操作是不允许的
  • Gin
    • gin 快速开始
    • gin-swagger用法
  • Go 进阶
    • Go 指针
    • Go 中的 GC 演变是怎样的?
    • Go 的堆和栈
  • 面向对象
    • make 和 new 的区别
    • new(T) 和 &T{} 有什么区别?
  • 并发编程
    • Channel
    • Go语言 CSP 并发模型
    • GMP 模型原理
      • GMP 模型为什么要有 P ?
    • Go 协程池(goroutine pool)
    • Go语言常见的并发模式
    • Go并发实践:主动停止goroutine
  • 最佳实践
    • 发布Go语言模块
  • 软件包
    • 常用的GoLang包工具
    • Go的UUID生成
    • 现代化的命令行框架Cobra
    • 配置解析神器Viper
    • Go发送邮件gomail
    • Go反射框架Fx
    • NSQ消息队列的使用
    • Go爬虫框架colly
    • grpc-go 的安装和使用
Powered by GitBook
On this page
  • 标记清除法
  • 三色并发标记法
  • 延伸阅读

Was this helpful?

  1. Go 进阶

Go 中的 GC 演变是怎样的?

PreviousGo 指针NextGo 的堆和栈

Last updated 2 years ago

Was this helpful?

标记清除法

在 Go v1.3 之前采用的是 标记-清除(mark and sweep)算法。

它的逻辑是,先将整个程序挂起(STW, stop the world),然后遍历程序中的对象,只要是可达的对象,都会被标记保留(红色),而那些不可达的对象(白色),则会被清理掉,清理完成后,会恢复程序。然后不断重复该过程。

image0

这种标记-清除的算法,会有一段 STW 的时间,将整个程序暂停,这对于一些实时性要求比较高的系统是无法接受的。

另外,上面这个标记的过程扫描的是整个堆内存,耗时比较久,最重要的是,它在清除数据的时候,会产生堆内存的碎片。

因此从 Go v1.5 开始,就开始抛弃这种算法,而改用 三色并发标记法。

三色并发标记法

新算法的出现,必然是要解决旧算法存在的最关键问题 ,即STW 的暂停挂起导致的程序卡顿。

它的逻辑就是,准备三种颜色,分别对三种对象进行标记:

  • 黑色:检测到有被引用,并且已经遍历完它所有直接引用的对象或者属性

  • 白色:还没检测到有引用的对象(检测开始前,所有对象都是白色,检测结束后,没有被引用的对象都是白色,会被清查掉)

  • 灰色:检测到有被引用,但是他的属性还没有被遍历完,等遍历完后也会变成黑色

既然 STW 会挂起程序,那是不是可以考虑将其摘除呢?

摘除会带来一个问题就是在标记的时候,程序的运行会不断改变对象的引用路径,影响标记的准确性。

总结来说,就是当在标记的时候出现 :一个白色对象被黑色对象引用,同时该白色对象又被某个灰色(或者上级有灰色对象)对象取消引用的情况,就会标记不准确。

因此如果想摘除 STW,那就得规避掉上面这个场景出现。

解决方法是:使用 插入屏障 和 删除屏障

插入屏障

在A对象引用B对象的时候,B对象被标记为灰色。(将B挂在A下游,B必须被标记为灰色)

删除屏障

被删除的对象,如果自身为灰色或者白色,那么被标记为灰色。

延伸阅读

关于不使用 STW 带来的影响可以看一下这篇文章:

https://segmentfault.com/a/1190000022030353
[典藏版]Golang三色标记、混合写屏障GC模式图文全分析