Python的垃圾回收机制(引用计数)

Python的垃圾回收机制

Python的GC模块主要运用了“引用计数”(reference counting)来跟踪和回收垃圾。在引用计数的基础上,还可以通过“标记-清除”(mark and sweep)解决容器对象可能产生的循环引用的问题,并且通过“分代回收”(generation collection)以空间换取时间的方式来进一步提高垃圾回收的效率。

解释器在执行到定义变量的语法时,会申请内存空间来存放变量的值,而内存的容量是有限的,这就涉及到变量值所占用内存空间的回收问题,当一个变量值没有用了(简称垃圾)就应该将其占用的内存给回收掉,那什么样的变量值是没有用的呢?

​ 单从逻辑层面分析,我们定义变量将变量值存起来的目的是为了以后取出来使用,而取得变量值需要通过其绑定的直接引用(如x=10,10被x直接引用)或间接引用(如l=[x,],x=10,10被x直接引用,而被容器类型l间接引用),所以当一个变量值不再绑定任何引用时,我们就无法再访问到该变量值了,该变量值自然就是没有用的,就应该被当成一个垃圾回收。

​ 毫无疑问,内存空间的申请与回收都是非常耗费精力的事情,而且存在很大的危险性,稍有不慎就有可能引发内存溢出问题,好在Cpython解释器提供了自动的垃圾回收机制来帮我们解决了这件事。

引用计数

引用计数:内存中的值被引用的次数,当计数为0时,该变量值就成为了垃圾,就会被回收。
下述情况计数会加1:
对象被创建 a=14
对象被引用 b=a
对象被作为参数,传到函数中 func(a)
对象作为一个元素,存储在容器(比如数组、列表、元组)中 List={a,“a”,“b”,2}

与上述情况相对应,当发生以下四种情况时,计数器-1
当该对象的别名被显式销毁时 del a
当该对象的引别名被赋予新的对象 a=26
一个对象离开它的作用域,例如 func函数执行完毕时,函数里面的局部变量的引用计数器就会减一(但是全局变量不会)
将该元素从容器中删除时,或者容器被销毁时。
 

PyObject

  1. python里每一个东西都是对象,它们的核心就是一个结构体:PyObject
  2. PyObject是每个对象必有的内容,其中ob_refcnt就是做为引用计数。当一个对象有新的引用时,它的ob_refcnt就会增加,当引用它的对象被删除,它的ob_refcnt就会减少

引用计数优缺点

  1. 优点 
    简单实时,一旦没有引用,内存就直接释放了。不用像其他机制等到特定时机。实时性还带来一个好处:处理回收内存的时间分摊到了平时。
  2. 缺点 
    维护引用计数消耗资源,会造成循环引用导致无法回收,造成内存泄露

循环应用

list1 = []

list2 = []

list1.append(list2)

list2.append(list1)
  • 1
  • 2
  • 3
  • 4
  • list1与list2相互引用,如果不存在其他对象对它们的引用,list1与list2的引用计数也仍然为1,所占用的内存永远无法被回收,这将是致命的。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值