标记,扫地,整理
最后更新于:2022-04-02 04:09:18
[TOC]
## 什么场景下gc很重要
- 内存需要被反复利用的场景
- 大量的对象在被分配和回收
- 高并发场景
## 标记(Mark-Sweep)算法
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/e2/c7/e2c772ae72dccab8fa4ad70923aab239_800x556.png)
- 栈中分配的对象存入一个集合中( Root set)
- 每次遍历 Rootlet中的对象追溯Heap中的对象进行分析
- 分成两个阶段标记(Mark)和清扫( Sweep)阶段
- Mak负责标记在使用的对象
- Sweep负责删除不被使用的对象
**Mark 阶段**
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/6e/f7/6ef7d06f36964fb6851f72bd785d1036_400x281.png)
**Sweep阶段**
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/9f/ca/9fca73222b6cd8d6492610c8517c5b1b_400x272.png)
删除没有被标记的对象
## gc时程序状态
### STP(Stop The World) 模型
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/ad/6a/ad6a1feda95f6ed9764605587b6bb243_400x81.png)
执行时每一个阶段,都要全部执行完全
### Increment Update 模型
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/62/e7/62e7b5fccb9415bc03e1da6332a89d56_400x58.png)
每个阶段多次执行
## Stop-the-world 问题
很难做到不STW,但是可以考虑缩短STW的时间,让用户感知到的是一个连续的模型
## 三色标记
go 使用 三色
白色:需要回收
黑色:不回收
灰色:中间地带
Root->白->灰
扫描 root set,找到白色节点标记成灰色
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/a9/84/a984839a72ba07e8404196f732aa76dd_400x278.png)
灰->黑
以灰色节点为起始点,做一次BFS。之前的灰色节点标黑,剩下的白色节点就是需要回收的
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/c0/c3/c0c30d637a21234c43d5f90abbc8731d_400x271.png)
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/6a/be/6abe6229a585d7d5aedd61264401a581_400x272.png)
**会不会有 mutation违反性质**
- 方法
- 读取白色节点时增加一个读屏障( read barrier),禁止读取
- 改变一个黑色节点时增加一个写屏障 write barrier),写入结束后,将这个节点标记成为灰色。
- 严格保证了不会有黑色节点指向白色节点。
';