Python中的垃圾回收机制是什么

一、写在前面:

我们都知道Python一种面向对象的脚本语言,对象是Python中非常重要的一个概念。在Python中数字是对象,字符串是对象,任何事物都是对象,而它们的核心就是一个结构体--PyObject。

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

PyObject是每个对象必有的内容,其中ob_refcnt就是做为引用计数。

二、垃圾回收机制

垃圾回收(Garbage Collection)大家应该多多少少都听过,但是什么是垃圾回收呢?我们这里说的垃圾回收肯定不是把垃圾丢进垃圾桶。现在的高级语言Java,C#等,都采用了垃圾回收机制,而不再是C,C++里用户自己管理维护内存的方式,自己管理内存是很自由,但是可能出现内存泄漏,悬空指针等问题。而垃圾回收机制作为现代编程语言的自动内存管理机制,专注于两件事:1. 找到内存中无用的垃圾资源 2. 清除这些垃圾并把内存让出来给其他对象使用。

三、Python中的垃圾回收

在Python中,垃圾回收机制主要是以引用计数为主要手段,以标记清除和分代回收机制作为辅助手段实现的。

1、引用计数

通过前面的介绍,我们已经知道PyObject是每个对象必有的内容,而当一个对象有新的引用时,它的ob_refcnt就会增加,当引用它的对象被删除,它的ob_refcnt就会减少,当引用计数为0时,该对象生命就结束了。

我们来看看引用计数+1的情况有什么:

(1)对象被创建:

zz.png

这里实际上123这个对象并没有在内存中新建,因为在Python启动解释器的时候会创建一个小整数池,在-5~256之间的整数对象会被自动加载到内存中等待调用。因此a=123是对123这个整数对象增加了一次引用。而456是不在整数池里的,需要创建对象,那么最后的引用次数是2呢?因为sys.getrefcount(b)也是一次引用。

(2)对象被引用:

xx.png

每一次赋值操作都会增加数据的引用次数,要记住引用的变量a、b、c指向的是数据456,而不是变量本身。

(3)对象作为参数传递到函数中:

cc.png

这里可以很明显看到在被传递到函数中后,引用计数增加了1。

(4)对象作为元素储存到容器中:

vv.png

这里我们在创建对象之后,把a分别添加到了一个列表和一个元组中,引用计数都增加了。

虽然引用计数必须在每次分配合释放内存的时候加入管理引用计数的操作,然而与其他垃圾回收技术相比,引用计数有一个优点,那就是“实时性”,如果这个对象没有引用,内存就直接释放了,而其他垃圾回收技术必须在某种特殊条件下才能进行无效内存的回收。但是引用计数带来的维护引用计数的额外操作和Python中进行的内存分配和释放,引用的赋值次数成正比的。除此之外,引用计数机制的还有一个软肋--无法解决循环引用带来的问题。循环引用可以使一种引用对象的引用计数不为0,然而这些对象实际上并没有被任何外部对象所引用,它们之间只是相互引用,这意味着这组对象所占用的内存空间是应该被回收的,但是由于循环引用导致的引用计数不为0,所以这组对象所占用的内存空间永远不会被释放。如下,list1与list2相互引用,如果不存在其他对象对它们的引用,list1与list2的引用计数也仍然为1,所占用的内存永远无法被回收,这将是致命的。

list1 = []
list2 = []
list1.append(list2)
list2.append(list1)

2、标记清除

标记清除(Mark—Sweep)算法是一种基于追踪回收(tracing GC)技术实现的垃圾回收算法。它分为两个阶段:第一阶段是标记阶段,GC会把所有的活动对象打上标记,第二阶段是把那些没有标记的对象非活动对象进行回收。

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

1562145716(1).png

        

在上图中,可以从程序变量直接访问块1,并且可以间接访问块2和3。程序无法访问块4和5。第一步将标记块1,并记住块2和3以供稍后处理。第二步将标记块2,第三步将标记块3,但不记得块2,因为它已被标记。扫描阶段将忽略块1,2和3,因为它们已被标记,但会回收块4和5。

标记清除算法作为Python的辅助垃圾收集技术,主要处理的是一些容器对象,比如list、dict、tuple等,因为对于字符串、数值对象是不可能造成循环引用问题。Python使用一个双向链表将这些容器对象组织起来。不过,这种简单粗暴的标记清除算法也有明显的缺点:清除非活动的对象前它必须顺序扫描整个堆内存,哪怕只剩下小部分活动对象也要扫描所有对象。

3、分代回收

分代回收是建立在标记清除技术基础之上的,是一种以空间换时间的操作方式。

Python将内存根据对象的存活时间划分为不同的集合,每个集合称为一个代,Python将内存分为了3“代”,分别为年轻代(第0代)、中年代(第1代)、老年代(第2代),他们对应的是3个链表,它们的垃圾收集频率与对象的存活时间的增大而减小。新创建的对象都会分配在年轻代,年轻代链表的总数达到上限时,Python垃圾收集机制就会被触发,把那些可以被回收的对象回收掉,而那些不会回收的对象就会被移到中年代去,依此类推,老年代中的对象是存活时间最久的对象,甚至是存活于整个系统的生命周期内。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/288275.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

瞬态抑制二极管(TVS)的注意事项与布局布线?|深圳比创达电子

一、瞬态抑制二极管(TVS)的注意事项 工作电压/反向截止电压(VRVRWM)此参数不需要降额,保证大于等于工作电路最大工作电压即可,越接近越好。该参数为TVS的固有参数。VBR是TVS固有参数,与外界冲击波形无关。 被保护器件…

分布式(8)

目录 36.什么是TCC? 37.分布式系统中常用的缓存方案有哪些? 38.分布式系统缓存的更新模式? 39.分布式缓存的淘汰策略? 40.Java中定时任务有哪些?如何演化的? 36.什么是TCC? TCC&#xff08…

低代码技术:颠覆数据孤岛的技术利器

在当今数据驱动的世界中,数据的价值无可忽视。然而,很多组织面临一个普遍的问题,即数据孤岛。数据孤岛指的是不同部门或系统之间无法有效共享和集成数据的情况。这限制了组织在数据驱动的决策和创新方面的能力。然而,低代码平台的…

雍禾植发成毛发行业标杆!雍禾医疗获“年度医疗大健康消费企业”

近期,以“新视野 新链接”为主题的2023 EDGE AWARDS全球创新评选榜单正式发布。该评选由钛媒体发起,聚焦大健康产业,由权威行业专家、王牌分析师、专业投资机构、用户代表共同评审,兼顾综合专业性、影响力、创新性三大维度评选而出…

2024 年加密货币领域需要注意的 5 大网络安全威胁

加密货币世界主要存在于数字领域,面临着众多不断变化的网络威胁,这些威胁所带来的风险,给个人和企业组织造成了重大损失。 本文将研究2023年年加密货币领域的一些关键网络安全趋势,这些趋势预计将持续到 2024 年,并对…

为什么大学c语言课不顺便教一下Linux,Makefile

为什么大学c语言课不顺便教一下Linux,Makefile,git,gdb等配套工具链呢? 在开始前我有一些资料,是我根据自己从业十年经验,熬夜搞了几个通宵,精心整理了一份「Linux的资料从专业入门到高级教程工具包」&…

kubeadm来快速搭建一个K8S集群

二进制搭建适合大集群,50台以下的主机 kubeadm更适合中下企业的业务集群 我们采用了二进制包搭建出的k8s集群,本次我们采用更为简单的kubeadm的方式来搭建k8s集群。 二进制的搭建更适合50台主机以上的大集群,kubeadm更适合中小型企业的集群…

Matplotlib基础

目录: 一、绘制函数图像:二、创建图形对象:三、绘制多子图: 一、绘制函数图像: from matplotlib import pyplot as plt import numpy as np #生成(-50,50)的数组 x np.arange(-50,50) #计算因…

SSM的校园二手交易平台----计算机毕业设计

项目介绍 本次设计的是一个校园二手交易平台(C2C),C2C指个人与个人之间的电子商务,买家可以查看所有卖家发布的商品,并且根据分类进行商品过滤,也可以根据站内搜索引擎进行商品的查询,并且与卖…

山海鲸可视化软件的优势:数据整合、可视化与个性化定制

随着科技的快速发展,企业数字化转型已成为必然趋势。而对于一些本身没有开发优势或非技术型企业,数字化产品的选择就成为重中之重。作为山海鲸可视化软件的开发者,我们深知这一点,对于企业来说,能选择一个产品一定要有…

【代数学作业5】理想的分解:高斯整数环中理想的结构,并根据其范数和素数的性质进行分解

【代数学作业5】理想的分解 写在最前面题目1相关概念题解分析1. ( 1 3 ) ( 1 − 3 ) (1 \sqrt{3}) (1 - \sqrt{3}) (13 ​)(1−3 ​)2. ( 4 3 ) ≠ ( 4 − 3 ) (4 \sqrt{3}) \neq (4 - \sqrt{3}) (43 ​)​(4−3 ​)3. ( 33 , 7 − 3 3 ) ( 4 3 3 ) (33, 7 - 3\sq…

开源大模型应用开发

1.大语言模型初探 ChatGLM3简介 ChatGLM3-6B 是一个基于 Transformer 的预训练语言模型,由清华大学 KEG 实验室和智谱 AI 公司于 2023 年共同训练发布。该模型的基本原理是将大量无标签文本数据进行预训练,然后将其用于各种下游任务,例如文…

边坡安全监测预警系统——高效率

安装边坡安全监测预警系统的原因是多方面的,涉及到社会效益、经济效益和环境效益。随着国家基础设施建设的快速发展,边坡安全监测预警系统的需求越来越迫切。 边坡安全监测预警系统对于保障人民生命财产安全具有重要意义。在山区、丘陵地带,边…

1.C++语言的编译器及编译流程

1.C编译器 编译器就是将“高级语言”翻译为“机器语言(低级语言)”的程序。以下是一些主流的C编译器及其简要用法: GNU Compiler Collection (GCC):’ GCC原名GNU C Compiler,后来逐渐支持更多的语言编译(C、Fortran、…

js文件上传 分片上传/断点续传/极速秒传

(极速秒传)利用md5判断上传的文件是否存在 MD5信息摘要算法,一种被广泛使用的密码散列函数,可以产生出一个128位(16字节)的散列值(hash value),用于确保信息传输完整一致。 每一个文件都会生成…

电磁波的信号加载说明

电磁波的信号加载电磁波(Electromagnetic wave)是由同相振荡 且互相垂直的电场与磁场在空间中衍生发射的振荡粒子波,是以波动的形式传播的电磁场,具有波粒二象性,其粒子形态称为光子,电磁波与光子不是非黑即白的关系,而…

Kubernetes 核心实战之一(精华篇 1/2)

文章目录 1,资源创建方式1.1 yaml1.2 命令行 2,NameSpace命名空间2.1 命令行创建ns2.2 yaml 创建ns 3,Pod3.1 命令行 创建pod3.2 yaml 创建pod3.3 可视化界面 创建3.3.1 Pod nginx3.3.2 Pod nginx tomcat3.3.3 Pod 2ngnix 1,资源…

日文游戏翻译 ,如何做好本地化翻译?

相关调查显示,日本游戏占据全球游戏市场约20%的份额,其销量一直都不错。市场上对于日语游戏翻译的需求也很大。那么,针对日文游戏翻译,如何做好本地化翻译? 首先、做好语言和文化上的本地化。这要求译员从翻译的文本到…

一篇关于大模型在信息抽取(实体识别、关系抽取、事件抽取)的研究进展综述

信息提取(IE)旨在从普通自然语言文本中提取结构化知识(如实体、关系和事件)。最近,生成式大型语言模型(LLMs)展现了在文本理解和生成方面的卓越能力,使得它们能够广泛应用于各种领域…

VINS-MONO拓展1----手写后端求解器,LM3种阻尼因子策略,DogLeg,构建Hessian矩阵

文章目录 0. 目标及思路1. 非线性优化求解器2. 基于VINS-MONO的Marginalization框架构建Hessian矩阵2.1 estimator.cpp移植2.2 solve.cpp/preMakeHessian()2.3 solve.cpp/makeHessian() 3. solve.cpp/solveLinearSystem()求解正规方程4. 更新状态5. 迭代求解6. EVO评估结果7. 待…