Python的垃圾回收机制详解


Posted in Python onAugust 28, 2019

引用计数

在Python源码中,每一个对象都是一个结构体表示,都有一个计数字段。

typedef struct_object {
  int ob_refcnt;
  struct_typeobject *ob_type;
} PyObject;

PyObject是每个对象必有的内容,其中ob_refcnt就是作为引用计数。当一个对象有了新的引用时,它的ob_refcnt就会增加,引用它的对象被删除时则减少。一旦对象的引用计数为0,该对象立即被回收,占用空间就会被释放。

优点

  • 简单易用
  • 实时性好,一旦没有引用就会被立即释放

缺点

  • 需要额外空间去维护引用计数
  • 不能解决对象的循环引用

对象的循环引用
循环引用是指两个对象相互引用且没有外部变量引用其中任何一个,导致引用链形成一个环。

>>> a = {}    # 对象a的引用计数为1
>>> b = {}    # 对象b的引用计数为1
>>> a['b'] = b  # b的引用计数增加1
>>> b['a'] = a  # a的引用计数增加1
>>> del a     # a的引用计数减少1,最后a的引用为1
>>> del b     # b的引用计数减少1,最后b的引用为1

在执行完del操作之后,没有任何引用指向a、b对象,但是由于这两个对象各自包含一个对对方的引用,所以引用计数始终保持在1。

按照引用计数中内存回收的原理,由于a和b的计数不为0,所以在使用引用计数法进行内存管理的时候这两个对象不会被回收,它们会一直驻留在内存中,造成内存泄露。

标记清除

标记清除机制主要用于解决循环引用问题。

标记清除算法是一种基于追踪回收(tracing GC)技术实现的垃圾回收算法。主要分为两个阶段:

  • 标记阶段,GC会将所有的活动对象打上标记
  • 对那些没有打上标记的非活动对象进行回收

区分活动对象与非活动对象

对象之间通过引用即指针连接在一起,构成一个有向图,对象就是这个有向图的节点,而引用关系构成这个有向图的边。从根对象(root object)出发,沿着有向边遍历对象,可达的对象会被标记为活动对象,不可达的对象就是要被清除的非活动对象。

根对象一般是全局变量、调用栈、寄存器等。

适用范围

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

对于标记清除算法来说,有一个比较明显的缺点:为了清除非活动对象,需要扫描整个堆内存,哪怕只剩下小部分活动对象也需要扫描所有对象。

分代回收

分代回收是一种以空间换时间的操作方式,建立在标记清除技术的基础之上,也是Python辅助的垃圾收集技术,主要用于处理容器对象。

Python会将内存根据对象的存活时间划分为不同的集合,每个集合称为一个代,主要会被分为3代:年轻代。中年代和老年代,它们会对应3个链表,对应的垃圾收集频率随着对象存活时间的增大而减小。

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

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python判断一个集合是否包含了另外一个集合中所有项的方法
Jun 30 Python
Python遍历文件夹和读写文件的实现方法
May 10 Python
PyQt5每天必学之事件与信号
Apr 20 Python
解读python如何实现决策树算法
Oct 11 Python
浅谈python的输入输出,注释,基本数据类型
Apr 02 Python
使用 Python 快速实现 HTTP 和 FTP 服务器的方法
Jul 22 Python
Python中的引用和拷贝实例解析
Nov 14 Python
wxpython绘制音频效果
Nov 18 Python
Django+python服务器部署与环境部署教程详解
Mar 30 Python
django 解决自定义序列化返回处理数据为null的问题
May 20 Python
Django Admin 上传文件到七牛云的示例代码
Jun 20 Python
Python接收手机短信的代码整理
Aug 02 Python
Python通过cv2读取多个USB摄像头
Aug 28 #Python
python3.5 cv2 获取视频特定帧生成jpg图片
Aug 28 #Python
Django--权限Permissions的例子
Aug 28 #Python
Python中函数的返回值示例浅析
Aug 28 #Python
django认证系统实现自定义权限管理的方法
Aug 28 #Python
Python中注释(多行注释和单行注释)的用法实例
Aug 28 #Python
对Django的restful用法详解(自带的增删改查)
Aug 28 #Python
You might like
PHP与MySQL开发的8个技巧小结
2010/12/17 PHP
PHP生成随机数的方法实例分析
2015/01/22 PHP
PHP按符号截取字符串的指定部分的实现方法
2018/09/10 PHP
PHP PDOStatement::closeCursor讲解
2019/01/30 PHP
HTML代码中标签的全部属性 中文注释说明
2009/03/26 Javascript
jQuery 点击图片跳转上一张或下一张功能的实现代码
2010/03/12 Javascript
jquery.cookie.js 操作cookie实现记住密码功能的实现代码
2011/04/27 Javascript
js中document.getElementByid、document.all和document.layers区分介绍
2011/12/08 Javascript
javascript作用域容易记错的两个地方分析
2012/06/22 Javascript
JavaScript使用HTML5的window.postMessage实现跨域通信例子
2014/04/11 Javascript
JS+html5 canvas实现的简单绘制折线图效果示例
2017/03/13 Javascript
关于vue.js v-bind 的一些理解和思考
2017/06/06 Javascript
JavaScript输出所选择起始与结束日期的方法
2017/07/12 Javascript
解决Nodejs全局安装模块后找不到命令的问题
2018/05/15 NodeJs
Python中字符编码简介、方法及使用建议
2015/01/08 Python
教你用Type Hint提高Python程序开发效率
2016/08/08 Python
对pandas数据判断是否为NaN值的方法详解
2018/11/06 Python
Python3 批量扫描端口的例子
2019/07/25 Python
python读取csv文件指定行的2种方法详解
2020/02/13 Python
Django如何继承AbstractUser扩展字段
2020/11/27 Python
python如何修改文件时间属性
2021/02/05 Python
用CSS3打造HTML5的Logo(实现代码)
2016/06/16 HTML / CSS
IFCHIC台湾:欧美国际设计师品牌
2019/05/18 全球购物
阿迪达斯新加坡官方网站:adidas新加坡
2019/12/06 全球购物
linux比较文件内容的命令是什么
2015/09/23 面试题
初中国旗下的演讲稿
2014/08/28 职场文书
三潭印月的导游词
2015/02/12 职场文书
2015年综治维稳工作总结
2015/04/07 职场文书
刑事上诉状(量刑过重)
2015/05/23 职场文书
2015大学迎新标语
2015/07/16 职场文书
新郎父母婚礼致辞
2015/07/27 职场文书
简短清晨问候语
2015/11/10 职场文书
社会心理学学习心得体会
2016/01/22 职场文书
简历中的自我评价怎么写呢?
2019/04/30 职场文书
五年级作文之想象作文
2019/10/30 职场文书
一文带你理解vue创建一个后台管理系统流程(Vue+Element)
2021/05/18 Vue.js