【转载】Python垃圾回收机制
转载自 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代。以此类推。
分代回收建立在标记清除技术基础之上。