Python小白垃圾回收机制入门

作者:silencement 时间:2022-05-20 04:38:42 

引用计数

Python默认的垃圾收集机制是“引用计数”,每个对象维护了一个ob_ref字段。它的优点是机制简单,当新的引用指向该对象时,引用计数加1,当一个对象的引用被销毁时减1,一旦对象的引用计数为0,该对象立即被回收,所占用的内存将被释放。它的缺点是需要额外的空间维护引用计数,不过最主要的问题是它不能解决“循环引用”。

什么是循环引用?A和B相互引用而再没有外部引用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 的引用计数并删除了用于引用的变量名,可是由于两个对象各包含一个对方对象的引用,虽然最后两个对象都无法通过名字访问了,但引用计数并没有减少到零。因此这个对象不会被销毁,它会一直驻留在内存中,这就造成了内存泄漏。为了解决循环引用问题,Python引入了标记-清除和分代回收两种GC机制。

标记清除

标记——清除(Mark——Sweep)是一种基于追踪(Tracing)回收技术实现的垃圾回收算法,对象之间通过引用(指针)连在一起,构成一个有向图,对象构成这个有向图的节点,而引用关系构成这个有向图的边。从根对象(root object)出发,沿着有向边遍历对象,可达的对象标记为有用的对象,不可达的对象就是要被清除的对象。所谓根对象就是一些全局引用对象和函数栈中的引用,这些引用所引用的对象是不可被删除的。

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

分代回收

分代回收是一种以空间换时间的操作方式,Python将内存根据对象的存活时间划分为不同的集合,每个集合称为一个代,Python将内存分为了3“代”,分别为年轻代(第0代)、中年代(第1代)、老年代(第2代),他们对应的是3个链表,它们的垃圾收集频率与对象的存活时间的增大而减小。新创建的对象都会分配在年轻代,年轻代链表的总数达到上限时,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

来源:https://www.py.cn/faq/python/11244.html

标签:Python,垃圾回收机制
0
投稿

猜你喜欢

  • Python Pandas批量读取csv文件到dataframe的方法

    2022-12-15 17:05:03
  • 一文带你了解ChatGPT API的使用

    2023-11-21 23:37:18
  • python实现批量提取指定文件夹下同类型文件

    2023-11-17 17:13:31
  • Request.ServerVariables("HTTP_REFERER")的用法

    2008-06-19 13:33:00
  • python中获得当前目录和上级目录的实现方法

    2022-01-07 20:24:30
  • python队列通信:rabbitMQ的使用(实例讲解)

    2021-01-11 05:04:55
  • pycharm部署、配置anaconda环境的教程

    2022-08-23 11:50:54
  • 浅析python 定时拆分备份 nginx 日志的方法

    2023-08-04 06:03:37
  • 手把手教你pycharm专业版安装破解教程(linux版)

    2023-03-03 08:58:56
  • aspjpeg组件通用加水印函数代码

    2011-04-04 10:32:00
  • Java连接Sql数据库经常用到的操作

    2024-01-17 09:26:28
  • Python整数与Numpy数据溢出问题解决

    2023-02-02 00:39:36
  • 解决Django加载静态资源失败的问题

    2023-09-11 21:10:51
  • 10款顶级jQuery插件推荐

    2011-08-14 07:55:39
  • Oracle如何直接运行OS命令(下)第1/2页

    2010-07-30 13:26:00
  • 如何恢复数据库的账号 登录名/用户名等

    2024-01-25 08:08:47
  • 一文弄懂MySQL索引创建原则

    2024-01-14 07:38:25
  • CSS实例教程:复合型CSS条状图表(上)

    2010-01-23 12:43:00
  • Pycharm使用爬虫时遇到etree红线问题及解决

    2021-09-04 19:07:06
  • vue实现拖拽效果

    2024-05-02 16:59:58
  • asp之家 网络编程 m.aspxhome.com