本教材由知了传课辛苦制作而成,仅供学习使用,请勿用于商业用途!如进行转载请务必注明出处!谢谢!

垃圾回收

一、什么是垃圾回收?

对没用的内存资源进行自动回收

不回收容易引发内存泄露问题

二、垃圾回收常用方法

1.引用计数(reference counting)

原理是在每个对象内部维护一个整数值,叫做这个对象的引用计数,当对象被引用时引用计数加一,当对象不被引用时引用计数减一。当引用计数为 0 时,自动销毁对象。

注意:

  • 回收的是内存空间
  • 链式引用都要跟着更新计数

缺陷:

  • 不能解决循环引用的问题
  • 频繁更新引用计数降低了性能
package main import "fmt" func main() { name := "hallen" var ptrName *string = &name fmt.Println(&ptrName) //0xc00000602 *ptrName = "" // 引用 fmt.Println(&ptrName) //0xc00000602 }

2.标记-清除(mark & sweep)(golang 1.5以前用的)

标记:从程序的根节点开始, 递归遍历所有对象,将能遍历到的对象打上标记。

清除:将所有未标记的的对象当作垃圾销毁。

缺点:

  • 在标记时必须暂停整个程序,递归遍历,会消耗很多时间

3.三色标记算法(Go 1.5、Go 1.6。)也叫三色并发标记法

三色标记法是传统 Mark-Sweep 的一个改进,它是一个并发的 GC 算法。

通过三个阶段确定要清除的对象有哪些

原理:

  • 首先创建三个集合:白、灰、黑。
  • 新创建(访问过的对象)的对象放入白色集合中。
  • 然后从根节点开始遍历所有对象(注意这里并不递归遍历,只遍历一次),把遍历到的对象从白色集合放入灰色集合。
  • 之后遍历灰色集合,将灰色对象_引用的对象_从白色集合放入灰色集合,之后将此灰色对象放入黑色集合
  • 重复 上面一部,直到灰色中无任何对象
  • 通过write-barrier检测对象有变化,重复以上操作,直到灰色对象中没有对象
  • 收集所有白色对象(垃圾)

注意:

  • 如果没有STW,在标记的时候对象被引用了,会出现对象丢失现象,

缺陷:

  • 垃圾产生的速度会大于垃圾收集的速度,这样会导致程序中的垃圾越来越多无法被收集掉。

4.分代收集(Generational Garbage Collection)(java、.Net等用的就是这种)

分代收集也是传统 Mark-Sweep 的一个改进

原理如下:

  • 新对象放入第 0 代
  • 当内存用量超过一个较小的阈值时,触发 0 代收集
  • 第 0 代幸存的对象(未被收集)放入第 1 代
  • 只有当内存用量超过一个较高的阈值时,才会触发 1 代收集
  • 2 代同理

1366人已阅读,今天你学习了吗?

添加新回复