转载自 https://sutune.me/2018/10/14/python-GC/

python采用的是引用计数机制为主,标记-清除和分代收集两种机制为辅的策略。

引用计数

  • python,每个对象都有一个ob_refcnt字段,用来记录该对象被引用的次数
  • 当对象的引用计数为0时,该对象被回收,对象占用的内存空间被释放
  • 缺点是无法解决对象的循环引用,会造成内存泄漏。

导致引用计数加一的情况:

  • 对象被创建。例如 a = 23
  • 对象被引用。例如 b = a
  • 对象作为参数,传入到一个函数中。例如 func(a)
  • 对象作为一个元素,存储到容器中。例如 list_1 = [***, a]

导致引用计数减一的情况:
对象的别名被显式销毁。例如 del a
对象的别名被赋予新的对象。例如 a = 24
一个对象离开它的作用域,例如f函数执行完毕时,func函数中的局部变量(全局变量不会)
对象所在的容器被销毁,或从容器中删除对象

标记清除:一种基于追踪回收(tracing GC)技术实现的垃圾回收算法
分为两个阶段,第一阶段是标记阶段,GC会把所有的“活动对象”打上标记,第二阶段是把那些没有标记的对象“非活动对象”进行回收。
图片说明
对象之间通过引用(指针)连在一起,构成有向图,从根节点出发,可达对象标记为活动对象,不可达对象就是要清除的非活动对象。
主要用来处理list,dict,tuple等容器对象,因为对于字符串、数值对象不可能造成循环引用问题。
确定是必须顺序扫描整个堆内存。

分代回收:
一种以时间换空间的操作方式,Python将内存根据对象的存活时间划分为不同的集合,每个集合称为一个代,Python将内存分为了3代,分别是0代, 1代, 2代。它们对应3个链表,其垃圾回收频率随着对象存活时间的增大而减小。
新创建的对象都会分配在0代,0代链表的总数达到上限时,Pyhton垃圾回收机制就会被触发,把那些可以被回收的对象回收掉,不会被回收的对象被移到1代。以此类推。
分代回收建立在标记清除技术基础之上。