【转载】Python中的垃圾回收机制
GC作为现代编程语言的自动内存管理机制,专注于两件事:1. 找到内存中无用的垃圾资源 2. 清除这些垃圾并把内存让出来给其他对象使用。GC彻底把程序员从资源管理的重担中解放出来,让他们有更多的时间放在业务逻辑上。但这并不意味着码农就可以不去了解GC,毕竟多了解GC知识还是有利于我们写出更健壮的代码。
引用计数
Python语言默认采用的垃圾收集机制是『引用计数法 Reference Counting』,该算法最早George E. Collins在1960的时候首次提出,50年后的今天,该算法依然被很多编程语言使用,『引用计数法』的原理是:每个对象维护一个ob_ref字段,用来记录该对象当前被引用的次数,每当新的引用指向该对象时,它的引用计数ob_ref加1,每当该对象的引用失效时计数ob_ref减1,一旦对象的引用计数为0,该对象立即被回收,对象占用的内存空间将被释放。它的缺点是需要额外的空间维护引用计数,这个问题是其次的,不过最主要的问题是它不能解决对象的“循环引用”,因此,也有很多语言比如Java并没有采用该算法做来垃圾的收集机制。
什么是循环引用?A和B相互引用而再没有外部引用A与B中的任何一个,它们的引用计数虽然都为1,但显然应该被回收,例子:
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对象已经没有任何引用指向这两个对象,但是这两个对象各包含一个对方对象的引用,虽然最后两个对象都无法通过其它变量来引用这两个对象了,这对GC来说就是两个非活动对象或者说是垃圾对象,但是他们的引用计数并没有减少到零。因此如果是使用引用计数法来管理这两对象的话,他们并不会被回收,它会一直驻留在内存中,就会造成了内存泄漏(内存空间在使用完毕后未释放)。为了解决对象的循环引用问题,Python引入了标记-清除和分代回收两种GC机制。
标记清除
『标记清除(Mark—Sweep)』算法是一种基于追踪回收(tracing GC)技术实现的垃圾回收算法。它分为两个阶段:第一阶段是标记阶段,GC会把所有的『活动对象』打上标记,第二阶段是把那些没有标记的对象『非活动对象』进行回收。那么GC又是如何判断哪些是活动对象哪些是非活动对象的呢?
对象之间通过引用(指针)连在一起,构成一个有向图,对象构成这个有向图的节点,而引用关系构成这个有向图的边。从根对象(root object)出发,沿着有向边遍历对象,可达的(reachable)对象标记为活动对象,不可达的对象就是要被清除的非活动对象。根对象就是全局变量、调用栈、寄存器。

在上图中,我们把小黑圈视为全局变量,也就是把它作为root object,从小黑圈出发,对象1可直达,那么它将被标记,对象2、3可间接到达也会被标记,而4和5不可达,那么1、2、3就是活动对象,4和5是非活动对象会被GC回收。
标记清除算法作为Python的辅助垃圾收集技术主要处理的是一些容器对象,比如list、dict、tuple,instance等,因为对于字符串、数值对象是不可能造成循环引用问题。Python使用一个双向链表将这些容器对象组织起来。不过,这种简单粗暴的标记清除算法也有明显的缺点:清除非活动的对象前它必须顺序扫描整个堆内存,哪怕只剩下小部分活动对象也要扫描所有对象。
分代回收
分代回收是一种以空间换时间的操作方式,Python将内存根据对象的存活时间划分为不同的集合,每个集合称为一个代,Python将内存分为了3“代”,分别为年轻代(第0代)、中年代(第1代)、老年代(第2代),他们对应的是3个链表,它们的垃圾收集频率与对象的存活时间的增大而减小。新创建的对象都会分配在年轻代,年轻代链表的总数达到上限时,Python垃圾收集机制就会被触发,把那些可以被回收的对象回收掉,而那些不会回收的对象就会被移到中年代去,依此类推,老年代中的对象是存活时间最久的对象,甚至是存活于整个系统的生命周期内。同时,分代回收是建立在标记清除技术基础之上。分代回收同样作为Python的辅助垃圾收集技术处理那些容器对象
转载地址:https://foofish.net/python-gc.html
【转载】Python中的垃圾回收机制的更多相关文章
- Python中的垃圾回收机制
Python的垃圾回收机制 引子: 我们定义变量会申请内存空间来存放变量的值,而内存的容量是有限的,当一个变量值没有用了(简称垃圾)就应该将其占用的内存给回收掉,而变量名是访问到变量值的唯一方式,所以 ...
- python中的垃圾回收机制及原理
序言: 来一起看看: 不同于C/C++,像Python这样的语言是不需要程序员写代码来管理内存的,它的GC(Garbage Collection)机制 实现了自动内存管理.GC做的事情就是解放程序员的 ...
- Python 中的垃圾回收机制(转载)
from: https://foofish.net/python-gc.html GC作为现代编程语言的自动内存管理机制,专注于两件事:1. 找到内存中无用的垃圾资源 2. 清除这些垃圾并把内存让出来 ...
- Python 中的垃圾回收机制--备忘
GC作为现代编程语言的自动内存管理机制,专注于两件事:1. 找到内存中无用的垃圾资源 2. 清除这些垃圾并把内存让出来给其他对象使用.GC彻底把程序员从资源管理的重担中解放出来,让他们有更多的时间放在 ...
- Python中的垃圾回收机制(转)
原文:https://foofish.net/python-gc.html GC作为现代编程语言的自动内存管理机制,专注于两件事:1. 找到内存中无用的垃圾资源 2. 清除这些垃圾并把内存让出来给其他 ...
- Python 中的垃圾回收机制
GC作为现代编程语言的自动内存管理机制,专注于两件事:1. 找到内存中无用的垃圾资源 2. 清除这些垃圾并把内存让出来给其他对象使用.GC彻底把程序员从资源管理的重担中解放出来,让他们有更多的时间放在 ...
- Python中的垃圾回收与del语句
python中的垃圾回收采用计数算法 一个对象如果被引用N次,则需要N次(即计算引用次数为零时)执行del 才能回收此对象. a = 100 b = a del a print(b) print(a) ...
- Java中的垃圾回收机制
1. 垃圾回收的意义 在C++中,对象所占的内存在程序结束运行之前一直被占用,在明确释放之前不能分配给其它对象:而在Java中,当没有对象引用指向原先分配给某个对象的内存时,该内存便成为垃圾.JVM的 ...
- python入门之垃圾回收机制
目录 一 引入 二.什么是垃圾回收机制? 三.为什么要用垃圾回收机制? 四.垃圾回收机制原理分析 4.1.什么是引用计数? 4.2.引用计数扩展阅读 4.2.1 标记-清除 4.2.2 分代回收 一 ...
随机推荐
- thinkphp自动映射分析
thinkphp的字段映射功能可以隐藏表单中真正的字段名,自动映射到真正的数据库字段,如表单中input的提交的名字为mail,而数据库中存的是email实现的原理非常简单首先定义一个映射的数组,以下 ...
- Angular2入门:TypeScript的类 - 参数属性:定义和初始化类成员
- 翻译:delete语句(已提交到MariaDB官方手册)
本文为mariadb官方手册:DELETE语句的译文. 原文:https://mariadb.com/kb/en/delete/ 我提交到MariaDB官方手册的译文:https://mariadb. ...
- SpringBoot之打成war包部署到Tomcat
正常情况下SpringBoot项目是以jar包的形式,正常情况下SpringBoot项目是以jar包的形式,并且SpringBoot是内嵌Tomcat服务器,所以每次重新启动都是用的新的Tomcat服 ...
- maven 工程依赖了某个jar包 但还是报java.lang.ClassNotFoundException的问题
一般出现这种情况,首先看看 pom.xml 文件引用的jar文件有没有损坏.或者下载不完整,打开maven仓库根据依赖地址可以查看. 如果还是出现问题,报 java.lang.ClassNotFoun ...
- JavaScript 获取按键,并屏蔽系统 Window 事件
// JavaScript 获取按键,并屏蔽系统 Window 事件 window.document.onkeydown = onkeydown; function onkeydown(event) ...
- RNN-LSTM入门
RNN-LSTM入门 Last Edited: Dec 02, 2018 10:20 PM Tags: 机器学习,论文阅读 RNN-Recurrent Neural Network 概念: 序列数据: ...
- MVC3中 ViewBag、ViewData和TempData的使用和区别(转载)
在MVC3开始,视图数据可以通过ViewBag属性访问,在MVC2中则是使用ViewData.MVC3中保留了ViewData的使用.ViewBag 是动态类型(dynamic),ViewData 是 ...
- Discuz网警过滤关键词库
积累近几年discuz关键词过滤 使用方法:1.进入后台/内容/词语过滤批量添加.2.打开CensorWords.txt,复制里面的文本信息到批量添加的输入框内,点击确定即可.如图: 关键词下载:Ke ...
- Java静态数据的初始化
Java中无论创建多少对象,静态数据都只占一份存储区域. 下面程序示例静态存储区域的初始化: //: initialization/StaticInitialization.java // Speci ...