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语言生成水仙花数代码示例
Dec 18 Python
python3.6+django2.0开发一套学员管理系统
Mar 03 Python
浅谈python连续赋值可能引发的错误
Nov 10 Python
Django中更改默认数据库为mysql的方法示例
Dec 05 Python
用django-allauth实现第三方登录的示例代码
Jun 24 Python
对Python获取屏幕截图的4种方法详解
Aug 27 Python
python 实现让字典的value 成为列表
Dec 16 Python
Python切割图片成九宫格的示例代码
Mar 10 Python
使用Pycharm(Python工具)新建项目及创建Python文件的教程
Apr 26 Python
python logging 重复写日志问题解决办法详解
Aug 04 Python
获取CSDN文章内容并转换为markdown文本的python
Sep 06 Python
Python djanjo之csrf防跨站攻击实验过程
May 14 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
地摊中国 - 珍藏老照片
2020/08/18 杂记
在任意字符集下正常显示网页的方法二(续)
2007/04/01 PHP
PHP的explode和implode的使用说明
2011/07/17 PHP
WordPres对前端页面调试时的两个PHP函数使用小技巧
2015/12/22 PHP
Windows下php+mysql5.7配置教程
2017/05/16 PHP
关于laravel后台模板laravel-admin select框的使用详解
2019/10/03 PHP
理解Javascript_06_理解对象的创建过程
2010/10/15 Javascript
两种不同的方法实现js对checkbox进行全选和反选
2014/05/13 Javascript
Javascript将字符串日期格式化为yyyy-mm-dd的方法
2016/10/27 Javascript
javaScript语法总结
2016/11/25 Javascript
JS中如何实现点击a标签返回页面顶部的问题
2017/01/19 Javascript
详解nodejs微信公众号开发——2.自动回复
2017/04/10 NodeJs
Vue 项目代理设置的优化
2018/04/17 Javascript
vue源码解析之事件机制原理
2018/04/21 Javascript
js使用formData实现批量上传
2020/03/27 Javascript
vue点击Dashboard不同内容 跳转到同一表格的实例
2020/11/13 Javascript
jQuery实现动态操作table行
2020/11/23 jQuery
[01:39](回顾)各路豪强针锋相对,几经鏖战四强产生
2014/07/01 DOTA
Python基础入门之seed()方法的使用
2015/05/15 Python
python3+PyQt5使用数据库表视图
2018/04/24 Python
使用python的pandas库读取csv文件保存至mysql数据库
2018/08/20 Python
查看Python依赖包及其版本号信息的方法
2019/08/13 Python
Python装饰器原理与基本用法分析
2020/01/07 Python
css3和jquery实现自定义checkbox和radiobox组件
2014/04/22 HTML / CSS
HTML5中的Web Notification桌面右下角通知功能的实现
2018/04/19 HTML / CSS
水果花束:Fruit Bouquets
2017/12/20 全球购物
Proenza Schouler官方网站:纽约女装和配饰品牌
2019/01/03 全球购物
宏碁西班牙官网:Acer西班牙
2021/01/08 全球购物
高中军训感言200字
2014/02/23 职场文书
春节联欢会主持词
2014/03/24 职场文书
党的群众路线教育实践活动领导班子对照检查材料
2014/09/25 职场文书
2014年大班保育员工作总结
2014/12/02 职场文书
2014年工作总结及2015工作计划
2014/12/12 职场文书
演讲比赛主持词
2015/06/29 职场文书
2016公司年会主持词
2015/07/01 职场文书
大学自主招生自荐信(2016精选篇)
2016/01/28 职场文书