首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >垃圾回收机制 | Python

垃圾回收机制 | Python

作者头像
阿珍
发布2025-05-14 17:47:41
发布2025-05-14 17:47:41
1340
举报

python采用的是引用计数机制为主,分代回收(隔代回收)标记-清除两种机制为辅的策略。

引用计数机制

正是因为有引用,对象才会在内存中存在。

引用计数是一种非常高效的内存管理手段,当一个pyhton对象被引用时其引用计数增加1,当其不再被引用时引用计数减1,当引用计数等于0的时候,对象就被删除了。

优点

  1. 实现简单。
  2. 垃圾回收的实时性。一旦没有引用,内存被直接释放;分摊处理内存回收的时间。

缺点

  1. 使用额外内存维护引用计数
  2. 循环引用导致内存泄漏

导致对象的引用计数+1的情况

  1. 创建对象
  2. 对象被引用
  3. 对象作为参数,传入到函数中
  4. 对象作为容器的元素,如l = [a, a]

导致对象的引用计数-1的情况

  1. 引用被重新赋值
  2. 引用被del,del删除的是引用,而不是对象
  3. 超过作用域
  4. 元素所在的容器被销毁

分代回收

从理论上说,对象的创建数目==释放数目。但是如果存在循环引用的话,肯定是创建>释放数量,当创建数与释放数量的差值达到规定的阈值的时候,当当当当~分代回收机制就登场啦。

Python根据对象的存活时间将内存划分为年轻代、中年代和老年代,分别用0,1,2表示。

越年轻的对象越容易死掉,老的对象通常会存活更久。 新生的对象被放入0代,如果该对象在第0代的一次gc垃圾回收中活了下来,那么它就被放到第1代里面(它就升级了)。如果第1代里面的对象在第1代的一次gc垃圾回收中活了下来,它就被放到第2代里面。

分代回收算法

  1. 从上一次第0代gc后,如果分配对象的个数减去释放对象的个数大于threshold0,那么就会对第0代中的对象进行gc垃圾回收检查。
  2. 从上一次第1代gc后,如果第0代被gc垃圾回收的次数大于threshold1,那么就会对第1代中的对象进行gc垃圾回收检查。
  3. 从上一次第2代gc后,如果第1代被gc垃圾回收的次数大于threshold2,那么就会对第2代中的对象进行gc垃圾回收检查。

gc.set_threshold(threshold0[, threshold1[, threshold2]) 设置各代执行垃圾回收的阈值。

有三种情况会触发垃圾回收:

  1. 调用gc.collect(),显式进行垃圾回收;
  2. 当gc模块的计数器达到阈值的时候;
  3. 程序退出的时候。

分代回收是建立在标记清除技术基础之上。分代回收同样作为Python的辅助垃圾收集技术处理那些容器对象,因为对于字符串、数值对象是不可能造成循环引用问题。

标记清除技术

标记清除用来解决循环引用产生的问题,循环引用只有在容器对象才会产生,比如字典,元祖,列表等。

在标记清除算法中有两个链表,root链表和unreachable链表。unreachable链表中的对象会被回收。

为什么设置两个链?

unreachable链表中可能存在被root链表中的对象、直接或间接引用的对象,这些对象是不能被回收的,一旦在标记的过程中,发现这样的对象,就将其从unreachable链表中移到root链表中;当完成标记后,unreachable链表中剩下的所有对象就是名副其实的垃圾对象了,接下来的垃圾回收只需限制在unreachable链表中即可。

Python使用一个双向链表将这些容器对象组织起来。不过,这种简单粗暴的标记清除算法也有明显的缺点:清除非活动的对象前它必须顺序扫描整个堆内存,哪怕只剩下小部分活动对象也要扫描所有对象。

本文系转载,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文系转载前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 引用计数机制
  • 分代回收
  • 标记清除技术
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档