Python垃圾回收机制详解:引用计数、标记清除与分代回收

Mia
Mia
发布时间:2026-10-14 | 5人浏览过
原创

本文深入解析Python默认的垃圾回收机制。首先介绍基于引用计数的基础回收原理及其无法处理循环引用的缺陷;接着阐述通过标记-清除算法解决容器对象的循环引用问题;最后详解分代回收技术,说明Python如何利用年轻代、中年代和老年代链表优化垃圾收集效率,帮助开发者理解内存管理并避免内存泄漏。

Python垃圾回收机制概述

引用计数

引用计数原理与局限

Python采用的默认垃圾收集策略是“引用计数”(Reference Counting)。每个对象内部都维护着一个名为 ob_ref 的字段来记录引用数量。这种机制的优势在于实现简单直观:每当有一个新的引用指向该对象时,其引用计数加1;当某个对象的引用被销毁或移除时,计数减1。一旦对象的引用计数降为0,该对象所占用的内存会立即被释放并回收。然而,这种方法也存在明显缺点:它需要额外的存储空间来维护引用计数,且最主要的问题是无法有效解决“循环引用”(Circular Reference)的情况。

所谓循环引用,是指两个或多个对象相互持有对方的引用,且不再有任何外部引用指向它们。例如,对象A和对象B互相引用,此时虽然它们的内部引用计数均为1(因为彼此指向对方),但从系统角度看,这两个对象已经无法被外部访问,理应被回收。具体示例如下:


a = { } # a 的引用为 1
b = { } # b 的引用为 1
a['b'] = b # b 的引用增 1,b的引用为2
b['a'] = a # a 的引用增 1,a的引用为 2
del a # a 的引用减 1,a的引用为 1
del b # b 的引用减 1, b的引用为 1

在上述代码执行过程中,del 语句虽然减少了变量 a 和 b 的引用计数并删除了这些变量名,但由于对象 a 内部包含对 b 的引用,对象 b 内部也包含对 a 的引用,导致两者的引用计数最终都停留在1,无法归零。因此,这些对象不会被销毁,而是长期驻留在内存中,从而引发内存泄漏。为了解决这一循环引用导致的内存泄漏问题,Python 引入了两种辅助垃圾收集(GC)机制:标记-清除(Mark-Sweep)和分代回收(Generational Collection)。

标记-清除算法解析

标记清除

标记-清除(Mark-Sweep)是一种基于追踪(Tracing)技术的垃圾回收算法。在Python中,对象之间通过引用(指针)连接,形成一个有向图,其中对象是图的节点,引用关系是图的边。算法从“根对象”(Root Object)出发,沿着有向边遍历所有可达的对象,并将这些可达对象标记为“有用对象”。那些从根对象出发无法到达的对象,则被视为不可回收对象,将被清除。这里的根对象通常指全局引用对象以及函数调用栈中的局部引用,这些对象及其引用的对象被视为程序运行所必需,不可被删除。

在Python中,标记-清除算法主要作为辅助技术,用于处理容器对象,例如 list、dict、tuple 以及自定义的 instance 等。这是因为字符串和数值等基本类型对象之间不可能形成循环引用,因此不需要此算法。Python 使用一个双向链表将这些容器对象组织起来,以便高效地进行标记和清除操作。

分代回收技术详解

分代回收

分代回收(Generational Collection)是一种以空间换时间的优化策略。Python 根据对象的存活时间将内存划分为不同的集合,称为“代”(Generation)。具体分为三代:年轻代(第0代)、中年代(第1代)和老年代(第2代)。每一代对应一个独立的链表,垃圾收集的频率与对象的存活时间成正比:对象存活时间越长,其所在代的收集频率越低。新创建的对象默认分配在年轻代。当年轻代链表中对象总数达到预设上限时,Python 的垃圾收集机制会被触发。在收集过程中,那些可以被回收的对象会被清理,而那些仍然存活的对象则会被移动到中年代。同理,从中年代存活下来的对象会进入老年代。老年代中的对象通常是存活时间最长的,甚至可能贯穿整个系统生命周期。此外,分代回收机制是建立在标记-清除技术基础之上的。

与标记-清除类似,分代回收同样作为Python的辅助垃圾收集技术,专门用于处理那些可能产生循环引用的容器对象。

代码实例演示

实例扩展:

引用计数实例


import sys
class A():
 def __init__(self):
  '''初始化对象'''
  print('object born id:%s' %str(hex(id(self))))
 def f1():
 '''循环引用'''
 while True:
  c1=A()
  c2=A()
  c1.t=c2
  c2.t=c1
  del c1
  del c2

到此这篇关于Python垃圾回收机制入门的文章就介绍到这了,更多相关Python垃圾回收机制详解内容请搜索本站以前的文章或继续浏览下面的相关文章,希望大家以后多多支持本站!

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表