Python垃圾回收主要以引用计数为主,分代回收为辅。
- 引用计数
引用计数法的原理是每个对象维护一个ob_ref,用来记录当前对象被引用的次数,也就是来追踪到底有多少引用指向了这个对象。当某个对象的引用计数为0,就进入了垃圾回收队列
当发生下列四种情况,引用次数会+1
(1)对象被创建
(2)对象被引用
(3)对象被作为参数,传到函数中
(4)对象作为一个元素,存储在容器中 List={a,”a”,”b”,2}
当发生下列四种情况,引用次数会+1
(1)当该对象的别名被显式销毁时 del a
(2)当该对象的引别名被赋予新的对象, a=26
(3)一个对象离开它的作用域,例如 func函数执行完毕时,函数里面的局部变量的引用计数器就会减一(但是全局变量不会)
(4)将该元素从容器中删除时,或者容器被销毁时。
缺点:引用计数无法解决循环引用问题,可能会导致内存泄漏(变量实际上已经没被) - 分代回收
由于引用计数法没有办法解决循环引用的问题,python还引入了标记-清除机制。分代回收就是基于标记-清除机制进行的。
Python中, 为了提高效率,引入了分代收集, 总共三个”代,年轻代(第0代)、中年代(第1代)、老年代(第2代)。Python 中, 一个代用链表存储, 所有属于同一”代”的内存块都链接在同一个链表中。
新创建的对象都会分配在年轻代,年轻代链表的总数达到上限时(阈值),Python垃圾收集机制就会被触发,把那些可以被回收的对象回收掉,而那些不会回收的对象就会被移到中年代去,老年代中的对象是存活时间最久的对象,甚至是存活于整个系统的生命周期内。
参考资料