当前位置:首页>python>Python学习笔记-GC垃圾回收机制

Python学习笔记-GC垃圾回收机制

  • 2026-10-25 07:00:15
Python学习笔记-GC垃圾回收机制

Python 的垃圾回收(Garbage Collection,GC)机制主要包括引用计数、标记 - 清除、分代回收这三部分,以下是详细介绍:

引用计数

引用计数是Python最基本的垃圾回收方式,Python为每个对象维护一个引用计数,记录对象被引用的次数。

  • 原理
    • 当一个对象被创建并赋值给一个变量时,对象的引用计数加1,如 a = [1, 2, 3],列表 [1, 2, 3] 的引用计数变为1。
    • 当对象被其他变量引用时,引用计数再加1,比如 b = a,此时列表 [1, 2, 3] 的引用计数变为2。
    • 当对象的引用被删除(变量被销毁或者变量重新赋值),引用计数减1,例如 del a,列表 [1, 2, 3] 的引用计数变为1 。
    • 当对象的引用计数变为0时,Python解释器会立即回收该对象所占用的内存空间。
  • 优点
    • 实时性
      能即时回收不再使用的对象,内存管理的响应速度快,不会造成大量内存碎片。
    • 简单高效
      实现原理简单,对大多数简单的对象回收场景,开销较小。
  • 缺点
    • 无法处理循环引用
      当对象之间存在循环引用时,尽管从外部来看这些对象已经不再被使用,但引用计数永远不会变为0,导致内存泄漏。例如两个对象互相引用:
classNode:def__init__(self):self.next = Nonea = Node()b = Node()a.next = bb.next = adel adel b

这里a和b形成循环引用,即使外部不再有对它们的引用,它们占用的内存也无法通过引用计数回收。

标记 - 清除

标记 - 清除算法是为了解决引用计数无法处理循环引用问题而引入的。

  • 原理
    • 标记阶段
      从一组被称为“根对象”(GC Roots)的对象集合开始,遍历整个对象图,标记所有从根对象可达的对象。根对象包括全局变量、函数栈中的局部变量等。
    • 清除阶段
      遍历整个堆内存,回收所有未被标记的对象,因为这些未被标记的对象意味着从根对象无法访问到,也就是不再被使用。
  • 优点
    有效解决了循环引用导致的内存泄漏问题。
  • 缺点
    • 暂停时间
      在标记和清除过程中,需要暂停程序的执行,可能会对程序的实时性产生一定影响。
    • 扫描开销
      每次回收都需要遍历整个堆内存,对于大型程序来说,这会带来一定的性能开销。

分代回收

分代回收是基于对象存活时间的一种优化策略,Python将对象分为0代、1代、2代三个“代”。

  • 原理
    • 对象分代
      新创建的对象都放在0代,当0代对象数量达到一定阈值(默认为700),会触发0代的垃圾回收,回收短命对象。存活下来的对象会被移到1代。
    • 代际回收
      每进行10次0代的垃圾回收,会触发1代的垃圾回收,回收较老的对象,存活下来的对象移到2代。每进行10次1代的垃圾回收,会触发2代的垃圾回收,回收所有对象。因为通常情况下,存活时间越长的对象,越有可能一直被使用,所以2代的扫描频率最低,以此来提高垃圾回收的整体效率。
  • 优点
    • 提高效率
      通过对不同代的对象采用不同的回收频率,减少了不必要的扫描,提高了垃圾回收的效率。
    • 适应对象生命周期特点
      符合大多数程序中对象的生命周期模式,新创建的对象往往很快就不再使用,而老对象则更倾向于长期存活。
  • 缺点
    • 复杂度增加
      分代回收机制增加了垃圾回收系统的复杂度,需要维护不同代的对象集合和回收策略。
    • 参数调整
      不同的应用场景可能需要调整分代回收的阈值等参数,如果参数设置不当,可能会影响垃圾回收的效果和性能。

流程图

               ┌───────────────────────────┐               │   对象创建 (new object)    │               └─────────────┬─────────────┘                             │                             ▼                   ┌──────────────────┐                   │ 引用计数机制      │                   │ (Reference Count)│                   └───────┬──────────┘                           │       ┌───────────────────┼───────────────────┐       │                   │                   │       ▼                   ▼                   ▼引用计数 > 0        引用计数 = 0        循环引用 (A↔B)(继续存活)          (立即释放对象)       (引用计数无法归零)                                               │                                               ▼                              ┌─────────────────────────┐                              │   标记-清除 (Mark-Sweep) │                              │   (检测不可达对象)       │                              └─────────────┬───────────┘                                            │                                            ▼                              ┌─────────────────────────┐                              │   分代回收 (Generational)│                              │   三代: 0代/1代/2代     │                              └─────────────┬───────────┘                                            │          ┌─────────────────────────────────┼────────────────────────────────┐          ▼                                 ▼                                ▼   ┌─────────────┐                  ┌─────────────┐                  ┌─────────────┐   │   0代 (young)│──幸存对象晋升──▶ │   1代 (middle)│──幸存对象晋升──▶ │   2代 (old)   │   └───────┬─────┘                  └───────┬─────┘                  └───────┬─────┘           │                                │                                │阈值触发(默认700) → 回收短命对象   每10次0代GC触发1次   每10次1代GC触发1次           │                                │                                │           ▼                                ▼                                ▼   ┌─────────────┐                  ┌─────────────┐                  ┌─────────────┐   │  0代 GC     │                  │  1代 GC     │                  │  2代 GC     │   │  快速清理   │                  │  清理更老对象│                  │  全面清理   │   └─────────────┘                  └─────────────┘                  └─────────────┘

相关的Python标准库函数

在Python中,可以使用gc模块来操作和控制垃圾回收机制:

  • gc.enable()
    启用垃圾回收机制。
  • gc.disable()
    禁用垃圾回收机制,一般不建议在正常开发中使用,可能会导致内存泄漏。
  • gc.collect([generation])
    手动触发垃圾回收,可以指定代际,如gc.collect(2) 表示触发2代的垃圾回收。
  • gc.set_threshold(threshold0[, threshold1[, threshold2]])
    设置分代回收的阈值,如gc.set_threshold(700, 10, 10) 。

最新文章

随机文章