Python垃圾回收机制

本文深入探讨Python垃圾回收机制,包括引用计数、标记清除及分代回收策略,旨在理解Python如何有效管理内存,解决循环引用问题并提高回收效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 垃圾回收机制

1.1 目的

Python 垃圾回收机制(Garbage Collection)主要使用引用计数(reference counting)来跟踪和回收垃圾。在引用计数的基础上,使用“标记-清除”(mark and sweep)解决容器对象可能产生的循环引用问题;使用“分代回收”(generation collection)以空间换时间的方法提高垃圾回收效率

2. 引用计数

Python垃圾回收主要以引用计数为主,分代回收为辅。引用计数法的原理是每个对象维护一个引用计数字段,用来记录当前对象被引用的次数,也就是来追踪到底有多少引用指向了这个对象,当发生以

下四种情况的时候,该对象的引用计数器+1:

  1. 对象被创建 (例如:a = 1)
  2. 对象被引用(例如:b = a)
  3. 对象被作为参数,传到函数中(例如:function(a))
  4. 对象作为一个元素,存储到容器中(例如:List = [0,1,2])

当发生以下四种情况时,该对象的引用计数器-1:

  1. 当该对象的别名被显式销毁时 (例如:del a)
  2. 当该对象的引别名被赋予新的对象 (a=26)
  3. 一个对象离开它的作用域,例如 func函数执行完毕时,函数里面的局部变量的引用计数器就会减一(但是全局变量不会)
  4. 将该元素从容器中删除时,或者容器被销毁时。

当指向该对象的内存的引用计数器为0的时候,该内存将会被Python虚拟机销毁。

2.1 引用计数的优缺点

引用计数法有很明显的优点:

  1. 高效
  2. 实时性:一旦没有引用,内存就直接释放了
  3. 对象有确定的生命周期
  4. 易于实现

原始的引用计数法也有明显的缺点:

  1. 维护引用计数消耗资源,维护引用计数的次数和引用赋值成正比,而不像mark and sweep等基本与回收的内存数量有关;
  2. 无法解决循环引用的问题。A和B相互引用而再没有外部引用A与B中的任何一个,它们的引用计数都为1,但显然应该被回收。
a = [1]
b = [2]
a.append(b)
b.append(a)

print(a)
print(b)

"""
运行结果:
[1, [2, [...]]]
[2, [1, [...]]]
"""

为了解决这两个致命弱点,Python又引入了以下两种GC机制。

3. 标记清除

标记清除Mark-Sweep是针对循环引用问题的回收机制,作用的对象是容器类型的对象(比如:list、set、dict等)。

它分为两个阶段:第一阶段是标记阶段,GC会把所有的『活动对象』打上标记,第二阶段是把那些没有标记的对象『非活动对象』进行回收。

标记清除算法作为Python的辅助垃圾收集技术主要处理的是一些容器对象,比如list、dict、tuple,instance等,因为对于字符串、数值对象是不可能造成循环引用问题。Python使用一个双向链表将这些容器对象组织起来。

标记-清除机制,顾名思义,首先标记对象(垃圾检测),然后清除垃圾(垃圾回收)。如图:
在这里插入图片描述
首先初始所有对象标记为白色,并确定根节点对象(这些对象是不会被删除),标记它们为黑色(表示对象有效)。将有效对象引用的对象标记为灰色(表示对象可达,但它们所引用的对象还没检查),检查完灰色对象引用的对象后,将灰色标记为黑色。重复直到不存在灰色节点为止。最后白色结点都是需要清除的对象。

标记清除的缺点:清除非活动的对象前它必须顺序扫描整个堆内存,哪怕只剩下小部分活动对象也要扫描所有对象。

4. 分代回收

分代回收是建立在标记清除基础上的一种辅助回收容器对象的GC机制。Python将内存根据对象的存活时间划分为不同的集合,每个集合称为一个代。Python将内存分为了3“代”,分别为年轻代(第0代)、中年代(第1代)、老年代(第2代),垃圾收集频率随对象的存活时间的增大而减小。

新创建的对象都会分配在年轻代,年轻代链表的总数达到上限时,Python垃圾收集机制就会被触发,把那些可以被回收的对象回收掉,而那些不会回收的对象就会被移到中年代去,依此类推,老年代中的对象是存活时间最久的对象,甚至是存活于整个系统的生命周期内。

同时,分代回收是建立在标记清除技术基础之上。分代回收同样作为Python的辅助垃圾收集技术处理那些容器对象

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值