引用计数
引用计数是指当对象的引用计数(指针数)为0时,表示这个对象不可达,需要被回收
1 | import os |
这个例子说明的是,a是局部变量,当包含a的函数执行完成之后,a的引用就变为0,也就被回收了,想要改变这种方式的话,只需要将a设置为global
变量即可
这里存在的问题是,如果a是被返回的值,那么列表a的生命周期就没有消失,仍然会继续占用内存
1 | def func(): |
查看对象的引用次数可用sys模块中的getrefcount
函数
1 | a = [] |
需要注意的是,函数调用时,函数本身和函数参数都会产生调用,sys.getrefcount()
并不是统计的指针数,而是统计指针指向的变量数量
1 | a = [] |
而回收内存的方法也很简单,先调用del语句,在强制调用gc.collect()
手动启动垃圾回收即可
循环引用
python中绝大部分都采用的引用计数
的垃圾回收机制,但是,当多个计数存在相互调用的情况下时,可能为内存带来很大的负担
1 | def func(): |
由上例可以看出,当func
函数执行完之后,按理说a, b的生命周期已经结束,但是可以看出内存并没有释放。因为他们还有相互引用,导致内存并没有释放。
如果想要回收内存,可以显示调用gc.collect()
手动启动垃圾回收
1 | func() |
python采用标记清除算法
和分代收集
,来启用针对循环引用的自动垃圾回收。
标记清除大致的意思是,python会想一个有向图一样去遍历每个节点,如果存在没有被标记的节点就会被回收,当然,不可能每次都去遍历全部节点,python采用的是双向链表维护了一个数据结构。
分代收集是指,python将所有对象分为三代。刚刚创建的对象为第0代,经过一次垃圾回收之后,依然存在的对象便会从上一代挪到下一代。而每一代都会有自动垃圾回收的阈值,值是可以单独指定的,当垃圾回收时,到达阈值时,对象就会被回收。