“麦冬”通过精心收集,向本站投稿了8篇Python的垃圾回收机制深入分析,以下是小编精心整理后的Python的垃圾回收机制深入分析,供大家参考借鉴,希望可以帮助到有需要的朋友。

篇1:Python垃圾回收机制
Python GC主要运用了“引用计数”(reference counting)来跟踪和回收垃圾,在引用计数的基础上,通过“标记-清除”(mark and sweep)解决容器对象可能产生的循环引用的问题。通过“分代回收”(generation collection)以空间换取时间来提高垃圾回收效率。
引用计数
在Python中,大多数对象的生命周期都是通过对象的引用计数来管理的。从广义上来讲,引用计数也是一种垃圾收集机制,而且也是一种最直观,最简单的垃圾收集技术。
原理:当一个对象的引用被创建或者复制时,对象的引用计数加1;当一个对象的引用被销毁时,对象的引用计数减1;当对象的引用计数减少为0时,就意味着对象已经没有被任何人使用了,可以将其所占用的内存释放了。
虽然引用计数必须在每次分配和释放内存的时候加入管理引用计数的动作,然而与其他主流的垃圾收集技术相比,引用计数有一个最大的有点,即“实时性”,任何内存,一旦没有指向它的引用,就会立即被回收。而其他的垃圾收集计数必须在某种特殊条件下(比如内存分配失败)才能进行无效内存的回收。
引用计数机制执行效率问题:引用计数机制所带来的维护引用计数的额外操作与Python运行中所进行的内存分配和释放,引用赋值的次数是成正比的。而这点相比其他主流的垃圾回收机制,比如“标记-清除”,“停止-复制”,是一个弱点,因为这些技术所带来的额外操作基本上只是与待回收的内存数量有关。
如果说执行效率还仅仅是引用计数机制的一个软肋的话,那么很不幸,引用计数机制还存在着一个致命的弱点,正是由于这个弱点,使得侠义的垃圾收集从来没有将引用计数包含在内,能引发出这个致命的弱点就是循环引用(也称交叉引用)。
问题:
循环引用可以使一组对象的引用计数不为0,然而这些对象实际上并没有被任何外部对象所引用,它们之间只是相互引用。这意味着不会再有人使用这组对象,应该回收这组对象所占用的内存空间,然后由于相互引用的存在,每一个对象的引用计数都不为0,因此这些对象所占用的内存永远不会被释放。比如:
a = []
b = []
a.append(b)
b.append(a)
print a
[[[…]]]
print b
[[[…]]]
这一点是致命的,这与手动进行内存管理所产生的内存泄露毫无区别。
要解决这个问题,Python引入了其他的垃圾收集机制来弥补引用计数的缺陷:“标记-清除”,“分代回收”两种收集技术。
标记-清除
“标记-清除”是为了解决循环引用的问题。可以包含其他对象引用的容器对象(比如:list,set,dict,class,instance)都可能产生循环引用。
我们必须承认一个事实,如果两个对象的引用计数都为1,但是仅仅存在他们之间的循环引用,那么这两个对象都是需要被回收的,也就是说,它们的引用计数虽然表现为非0,但实际上有效的引用计数为0,
我们必须先将循环引用摘掉,那么这两个对象的有效计数就现身了。假设两个对象为A、B,我们从A出发,因为它有一个对B的引用,则将B的引用计数减1;然后顺着引用达到B,因为B有一个对A的引用,同样将A的引用减1,这样,就完成了循环引用对象间环摘除。
但是这样就有一个问题,假设对象A有一个对象引用C,而C没有引用A,如果将C计数引用减1,而最后A并没有被回收,显然,我们错误的将C的引用计数减1,这将导致在未来的某个时刻出现一个对C的悬空引用。这就要求我们必须在A没有被删除的情况下复原C的引用计数,如果采用这样的方案,那么维护引用计数的复杂度将成倍增加。
原理:“标记-清除”采用了更好的做法,我们并不改动真实的引用计数,而是将集合中对象的引用计数复制一份副本,改动该对象引用的副本。对于副本做任何的改动,都不会影响到对象生命走起的维护。
这个计数副本的唯一作用是寻找root object集合(该集合中的对象是不能被回收的)。当成功寻找到root object集合之后,首先将现在的内存链表一分为二,一条链表中维护root object集合,成为root链表,而另外一条链表中维护剩下的对象,成为unreachable链表。之所以要剖成两个链表,是基于这样的一种考虑:现在的unreachable可能存在被root链表中的对象,直接或间接引用的对象,这些对象是不能被回收的,一旦在标记的过程中,发现这样的对象,就将其从unreachable链表中移到root链表中;当完成标记后,unreachable链表中剩下的所有对象就是名副其实的垃圾对象了,接下来的垃圾回收只需限制在unreachable链表中即可。
分代回收
背景:分代的垃圾收集技术是在上个世纪80年代初发展起来的一种垃圾收集机制,一系列的研究表明:无论使用何种语言开发,无论开发的是何种类型,何种规模的程序,都存在这样一点相同之处。即:一定比例的内存块的生存周期都比较短,通常是几百万条机器指令的时间,而剩下的内存块,起生存周期比较长,甚至会从程序开始一直持续到程序结束。
从前面“标记-清除”这样的垃圾收集机制来看,这种垃圾收集机制所带来的额外操作实际上与系统中总的内存块的数量是相关的,当需要回收的内存块越多时,垃圾检测带来的额外操作就越多,而垃圾回收带来的额外操作就越少;反之,当需回收的内存块越少时,垃圾检测就将比垃圾回收带来更少的额外操作。为了提高垃圾收集的效率,采用“空间换时间的策略”。
举例:
当某些内存块M经过了3次垃圾收集的清洗之后还存活时,我们就将内存块M划到一个集合A中去,而新分配的内存都划分到集合B中去。当垃圾收集开始工作时,大多数情况都只对集合B进行垃圾回收,而对集合A进行垃圾回收要隔相当长一段时间后才进行,这就使得垃圾收集机制需要处理的内存少了,效率自然就提高了。在这个过程中,集合B中的某些内存块由于存活时间长而会被转移到集合A中,当然,集合A中实际上也存在一些垃圾,这些垃圾的回收会因为这种分代的机制而被延迟。
在Python中,总共有3“代”,也就是Python实际上维护了3条链表。具体可以查看Python源码详细了解。
篇2:Python的垃圾回收机制深入分析
最近更 新
本地文件上传到七牛云服务器示例(七牛云存
python类定义的讲解
python中使用urllib2伪造HTTP报头的2个方
使用 Python 获取 Linux 系统信息的代码
用python实现的可以拷贝或剪切一个文件列
Python牛刀小试密码爆破
python获取豆瓣电影简介代码分享
python数据结构之二叉树的遍历实例
Python交换变量
python模拟登录百度代码分享(获取百度贴吧
热 点 排 行
Python入门教程 超详细1小时学会
python 中文乱码问题深入分析
比较详细Python正则表达式操作指
Python字符串的encode与decode研
Python open读写文件实现脚本
Python enumerate遍历数组示例应
Python 深入理解yield
Python+Django在windows下的开发
python 字符串split的用法分享
python 文件和路径操作函数小结
篇3:药品回收机制探讨
药品回收机制探讨
过期药品不仅危害身体健康,而且对环境造成污染.社会、政府应高度重视过期药品回收,建立过期药品长效回收机制.
作 者:段立华 张晓媛 DUAN Li-hua ZHANG Xiao-yuan 作者单位:河北化工医药职业技术学院,河北,石家庄,050026 刊 名:河北化工 英文刊名:HEBEI CHEMICAL ENGINEERING AND INDUSTRY 年,卷(期): 30(9) 分类号:X787 关键词:过期药品 回收 长效机制篇4:简单讲解Lua中的垃圾回收机制
这篇文章主要介绍了Lua中的垃圾回收机制,自动的垃圾回收是Lua的重要特性之一,需要的朋友可以参考下
Lua使用基于被内置在Lua某些算法的垃圾收集自动内存管理,可以自动内存管理的结果,作为一个开发者:
没有必要担心的对象分配内存。
无需释放他们时,不再需要可将其设置为nil。
Lua使用运行不时收集死的对象时,不再从Lua程序中访问垃圾收集器。
所有对象,包括表,用户数据,函数,线程,字符串等受自动内存管理。 Lua使用增量标记和使用两个数字来控制其垃圾回收周期即垃圾收集暂停和垃圾收集器的步骤事半功倍清除收集器。这些值是在百分比和100的值是常等于1。
垃圾收集暂停
垃圾收集停顿被用于控制多长时间的垃圾收集器需要等待,之前;它是由Lua的自动内存管理再次调用。数值低于100就意味着Lua中不会等待下一个周期。此值的类似地较高的值将导致垃圾收集器是缓慢的并且性质上较不积极。200表示该集合等待的总内存在使用中要开始一个新的周期开始前的两倍。因此,根据不同的性质和应用的速度,有可能要求改变该值来获得在Lua应用的最佳性能。
垃圾收集器的步骤事半功倍
这一步乘数控制垃圾收集在Lua程序的内存分配的相对速度。较大的步长值将导致垃圾收集器要更侵蚀性,同时也提高了垃圾收集的每个增量步的步长大小。值小于100可能经常导致避免垃圾收集器没有完成其周期和其一般不是优选的。默认值是200,这意味着垃圾收集器运行的两倍的内存分配的速度。
垃圾收集器函数
作为开发人员,我们确实有过让Lua自动内存管理。为此,有以下几种方法。
collectgarbage(“collect”): 执行垃圾回收的一个完整周期。
collectgarbage(“count”): 返回当前使用的千字节的程序内存量
collectgarbage(“restart”): 如果垃圾收集器已经停止,将重新启动它,
collectgarbage(“setpause”): 设置给定为第二参数除以100至垃圾收集器暂停变量的值。它的用途是作为讨论的一点上面。
collectgarbage(“setstepmul”): 设置给定为第二参数除以100到垃圾步骤乘数的变量的值。它的用途是作为讨论的一点上面。
collectgarbage(“step”): 运行垃圾回收的一步。第二个参数是越大step也会变大。在收集的垃圾将返回true,如果触发的步骤是一个垃圾收集周期的最后一步。
collectgarbage(“stop”): 停止垃圾收集器,如果它的运行。
使用垃圾收集器例如一个简单的例子如下所示。
代码如下:
mytable = {“apple”, “orange”, “banana”}
print(collectgarbage(“count”))
mytable = nil
print(collectgarbage(“count”))
print(collectgarbage(“collect”))
print(collectgarbage(“count”))
当我们运行上面的程序,会得到下面的输出。请注意,这样的结果会有所不同,由于在操作系统中,Lua自动内存管理功能可能也有差异。
代码如下:
20.9560546875
20.9853515625
0
19.4111328125
可以在上面的程序看出,一旦垃圾回收完成后,既可以减少使用内存。但是它也不是强制性的调用。即使我们不给调用,它也会自动在后一阶段在预定时间之后由Lua解释器执行。
显然我们可以改变,如果需要使用垃圾收集器的这些功能行为。这些功能提供了一点额外的能力,为开发者处理复杂情况。根据不同的内存需要执行程序类型,可能会或可能不会使用此功能。但在应用程序的内存使用情况,并在程序本身,以避免在部署后不想要对结果进行检查。
篇5:垃圾回收倡议书
廉江中学全体师生:
廉江中学是一间拥有八千多名师生的重点中学,有良好的教风和学风,但学校的垃圾处理问题却一直干扰着教学工作造成财产损失及影响学校形象。
1、如家属拾荒者(一般他们都衣食无忧)随意进入教室,可能导致师生资料当垃圾;
2、一些同学卫生意识淡薄,乱丢垃圾使校园污烟瘴气。
为了提高我校师生的卫生保洁意识,塑造学校的良好形象,我们向全校师生发出如下倡议:
1、积极行动起来做好各班、各处室的垃圾分类回收工作,将卖废物所得的钱用于资助我校特困学生。(垃圾回收可分为纸类和塑料类;据统计我校垃圾每月可卖得1000——1500元,按每人100元算,可支持10—15名特困生)。
2、深入开展“弯弯腰行动”,齐心协力消灭公共场所的脏乱现象。团干及青年团员要积极响应,担当表率。
3、养成把垃圾带走的良好习惯,从生活中的细节做起,从点滴小事做起,塑造自我良好形象。
5、回收量的多少(按斤计算)作为该班评优的材料,在升旗礼上每月公布一次,没有回收的班级点名批评。
6、回收量的多少由负责回收的学生会干部记录,垃圾所卖得到的资金由学生会保管,资金的用途将在公布栏上公布。
篇6:垃圾回收倡议书
亲爱的同学们:
美丽、和谐、整洁是我们理想中的校园。优美的`环境更是我们的追求。虽然我们的愿望非常美好,但是我们总是看到以下不和谐的画面:中、晚餐后,小卖部门口总是站满了身穿龙实中的校服的同学,在回寝室的路上,总是看到拿着饮料和零食的同学,那垃圾桶里的垃圾,总是多得放不下,可路过的你却视而不见,寝室里,总是有同学利用睡前的几分钟,泡方便面,弄得“香飘满室”。
因此,为了我们节约、简洁、环保的校园,我们七(2)班的同学提出了“垃圾回收”的倡议,初步方案如下:我们建议学校建立一个“垃圾回收站”,以一个班级为单位,各班同学收集学校内的饮料瓶、铝罐、废旧电池、废纸等垃圾,累积一个星期的时间,以市场收购价回收到校建立的“垃圾回收站”。再在班主任的合理调配下,用回收来的钱来做有意义的事情。
这样不仅美化了校园环境,增强了同学的环保意识,提高了同学对环保的重视,而且为公益事业做了贡献。
在此,我们发出倡议:为了我们校园的明天,让我们真正做到“垃圾回收”,时时刻刻把环保放在心中,自觉地为我们的校园减少白色污染,朝着我们的目标前进!
篇7:回收垃圾倡议书
地球是生命的摇篮,海岛是我们赖以生存的家园。近年来,随着经济社会的发展和人民生活水平的提高,垃圾产生量逐年增加,对环境的影响日益突出。对垃圾进行科学分类和无害化处理,对于解决环境污染问题、提高海岛文明程度、实现经济社会可持续发展具有重大意义。
为推进垃圾减量化、资源化、无害化,20__年伊始,县委、县政府在全县启动了垃圾分类减量工作。这项工作功在当代、利在千秋,需要我们每个单位、每个家庭、每个人的积极参与。为此,我们倡议:
1、提高垃圾分类意识、自觉做到分类收集、分类投放。
2、积极开展无纸化办公,减少一次性用品使用。
3、践行“光盘”行动,适当点餐,减少剩余。
4、拒绝购买过度包装商品,自带环保购物袋,优先选择耐用型、节能型、环保型商品。
爱护地球,保护环境,是我们每一个公民的责任和义务。让我们携起手来,从自身做起,从每个家庭做起,积极参与到生活垃圾分类减量行动中来,努力为我们的子孙后代留下青山绿水,为打造国际旅游避暑胜地、建设美丽长海贡献我们的一份力量!
长海县推进垃圾分类减量工作领导小组办公室
20__年2月25日
篇8:Java垃圾回收机制以及内存泄漏问题论文
有关Java垃圾回收机制以及内存泄漏问题论文
前言
在segmentfault上看到一个问题:java有完善的GC机制,那么在java中是否会出现内存泄漏的问题,以及能否给出一个内存泄漏的案例。本问题视图给出此问题的完整答案。
垃圾回收机制简介
在程序运行过程中,每创建一个对象都会被分配一定的内存用以存储对象数据。如果只是不停的分配内存,那么程序迟早面临内存不足的问题。所以在任何语言中,都会有一个内存回收机制来释放过期对象的内存,以保证内存能够被重复利用。
内存回收机制按照实现角色的不同可以分为两种,一种是程序员手动实现内存的释放(比如C语言)另一种则是语言内建的内存回收机制比如本文将要介绍的java垃圾回收机制。
Java的垃圾回收机制
在程序的运行时环境中,java虚拟机提供了一个系统级的垃圾回收(GC,Carbage Collection)线程,它负责回收失去引用的对象占用的内存。理解GC的前提是理解一些和垃圾回收相关的概念,下文一一介绍这些概念。
对象在jvm堆区的状态
Java对象的实例存储在jvm的堆区,对于GC线程来说,这些对象有三种状态。
1. 可触及状态:程序中还有变量引用,那么此对象为可触及状态。
2. 可复活状态:当程序中已经没有变量引用这个对象,那么此对象由可触及状态转为可复活状态。CG线程将在一定的时间准备调用此对象的finalize方法(finalize方法继承或重写子Object),finalize方法内的代码有可能将对象转为可触及状态,否则对象转化为不可触及状态。
3. 不可触及状态:只有当对象处于不可触及状态时,GC线程才能回收此对象的内存。
GC为了能够正确释放对象,必须监控每一个对象的运行状态,包括对象的申请、引用、被引用、赋值等,GC都需要进行监控,所以无论一个对象处于上文中的任何状态GC都会知道。
上文说到,GC线程会在一定的时间执行可复活状态对象的finalize方法,那么何时执行呢?由于不同的JVM实现者可能使用不同的算法管理GC,所以在任何时候,开发者无法预料GC线程进行各项操作(包括检测对象状态、释放对象内存、调用对象的finalize方法)的时机。虽然可以通过System.gc()和Runtime.gc()函数提醒GC线程尽快进行垃圾回收操作,但是这也无法保证GC线程马上就会进行相应的回收操作。
内存泄露
内存泄漏指由于错误的.设计造成程序未能释放已经不再使用的内存,造成资源浪费。GC会自动清理失去引用的对象所占用的内存。但是,由于程序设计错误而导致某些对象始终被引用,那么将会出现内存泄漏。
比如下面的例子。使用数组实现了一个栈,有入栈和出栈两个操作。
import com.sun.javafx.collections.ElementObservableListDecorator;import com.sun.swing.internal.plaf.metal.resources.metal_sv;import java.beans.ExceptionListener;import java.util.EmptyStackException;/** * Created by peng on 14-9-21. */public class MyStack { private Object[] elements; private int Increment = 10; private int size = 0; public MyStack(int size) { elements = new Object[size]; } //入栈 public void push(Object o) { capacity(); elements[size++] = o; } //出栈 public Object pop() { if (size == 0) throw new EmptyStackException(); return elements[--size]; } //增加栈的容量 private void capacity() { if (elements.length != size) return; Object[] newArray = new Object[elements.length + Increment]; System.arraycopy(elements, 0, newArray, 0, size); } public static void main(String[] args) { MyStack stack = new MyStack(100); for (int i = 0; i < 100; i++) stack.push(new Integer(i)); for (int i = 0; i < 100; i++) { System.out.println(stack.pop().toString()); } }}
这个程序是可用的,支持常用的入栈和出栈操作。但是,有一个问题没有处理好,就是当出栈操作的时候,并没有释放数组中出栈元素的引用,这导致程序将一直保持对这个Object的引用(此object由数组引用),GC永远认为此对象是可触及的,也就更加谈不上释放其内存了。这就是内存泄漏的一个典型案例。针对此,修改后的代码为:
//出栈 public Object pop() { if (size == 0) throw new EmptyStackException(); Object o = elements[--size]; elements[size] = null; return o; }












