Python垃圾回收机制

Python的垃圾回收主要通过引用计数、标记-清除和分代回收机制来管理内存。引用计数是最基本的方法,当对象的引用计数为0时,对象被视为垃圾。然而,循环引用问题导致引用计数无法准确回收,于是引入了标记-清除机制。此外,为了优化资源,Python还使用分代回收,将对象按生存时间分为不同代,不同代的回收频率不同,以平衡空间和时间效率。
摘要由CSDN通过智能技术生成

什么是垃圾回收

    当为一个变量分配数据的时候,python会在内存中分配一部分空间,用户储存此数据,但内存空间总是有限的,如果一直占用内存空间,内存迟早会溢出,所以,程序中需要把无用的数据从内存中删除,回收内存空间,这个过程就叫作垃圾回收。
    python采用的是引用计数机制为主,标记–>清除和分代收集(隔代回收)两种机制为辅的策略。

垃圾回收中的计数

    python里每一个东西都是对象,它们的核心就是一个结构体:PyObject
    PyObject是每个对象必有的内容,其中ob_refcnt就是做为引用计数。当一个对象有新的引用时,它的ob_refcnt就会增加,当引用它的对象被删除,它的ob_refcnt就会减少
    简单来说,当一个变量被赋值一次时,这个变量此时的计数为1,当这个变量被其它变量引用时,此时的计数将会加1,当引用它的对象被删除时,它的计数将会减少1,当计数为0时,此时的这个变量对应的数据则为垃圾数据,此数据就会被回收。

import sys
name = 'a'
print(sys.getrefcount(name))  # 返回值11,初始值为什么是11而不是1?后续需要查答案
name1 = name
print(sys.getrefcount(name))  # 返回值12,多引用了一次,计数器加1
name2 = name1
print(sys.getrefcount(name))  # 返回值13,再次引用,计数器加1
del name1
print(sys.getrefcount(name))  # 返回值12,删除一个变量,计数器减1

垃圾回收中的 标记->回收

计数问题产生了一个新的问题,就是循环引用无法回收,什么是循环引用,代码如下:

l1 = [1, 2]  # 此时l1的计数假设为1
l2 = [3, 4]  # 此时l2的计数假设为1
l1.append = l2  # 此时l2的计数为2
l2.append = l1  # 此时l1的计数为2
del l1  # 此时l1的计数为1
del l2  # 此时l2的计数为1

上面的代码可以明白,由于互相引用的情况下产生了循环引用,此时删除了l1与l2两个变量是无法让计数变为0的,那么内存就无法得到释放,为了解决这个问题,python出现了一个 标记 -> 回收机制。
当内存不够用时,python会去检查代码中的所有内存中的数据值,如果发现了一个循环引用的值时,就会打上标记,当python检查完内存中所有数据值时,将会一次性回收所有的被打过标记的数据值。

Python中的分代回收

分代回收是一种以空间换时间的机制。

  1. python会将内存对象根据存活时间划分为三个不同的集合。每个集合可以称为一个代。可以理解为“第0代”,“第1代”,“第2代”,他们对应的是3个链表,它们的垃圾收集频率随着对象存活时间的增大而减小。
  2. 新创建的对象都被分配到“第0代”中,当“第0代”的链表总数量达到上限时,python的垃圾回收机制将被触发,将回收可回收对象,并将不可回收对象放到“第1代”链表中,依次类推,“第2代”链表中的对象为存活时间最久的对象,甚至存活整个系统的生命周期内。
  3. 分代回收是建立在标记清除技术基础之上。分代回收同样作为Python的辅助垃圾收集技术处理那些容器对象。

而分代回收被创建的原因就是为了节省系统运行的资源,系统可能会频繁的去检查“第0代”链表中的对象,而对于“第1代”链表中的对象则相对来说不会太过频繁去检查,而“第2代”链表中的对象可能很长时间才会检查一次,以此来节省运算资源。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值