摘要:而采用的是引用计数机制为主,标记清理和分代收集两种机制为辅的策略。现在我们先去考虑一下,什么情况下引用计数,什么情况下,当引用次数为时,肯定就是需要进行回收的时刻。引用计数机制缺点维护引用计数需要消耗一定的资源循环应用时,无法回收。
上一篇文章:私有化规则与属性Property
下一篇文章:Python进程专题总览篇
高级语言一般都有垃圾回收机制,其中c、c++使用的是用户自己管维护内存的方式,这种方式比较自由,但如果回收不当也会引起垃内存泄露等问题。而python采用的是引用计数机制为主,标记-清理和分代收集两种机制为辅的策略。
1、引用计数python中一切皆对象,所以python底层计数结构地就可以抽象为:
引用计数结构体{ 引用计数; 引用的对象 }
是不是简单明了。现在我们先去考虑一下,什么情况下引用计数+1,什么情况下-1,当引用次数为0时,肯定就是需要进行回收的时刻。
1、对象被创建时,例如 mark="帅哥" 2、对象被copy引用时,例如 mark2=mark,此时mark引用计数+1 3、对象被作为参数,传入到一个函数中时 4、对象作为一个子元素,存储到容器中时,例如 list=[mark,mark2]
1、对象别名被显示销毁,例如 del mark 2、对象引用被赋予新的对象,例如mark2=mark3,此时mark引用计数-1(对照引用计数+1的情况下的第二点来看) 3、一个函数离开他的作用域,例如函数执行完成,它的引用参数的引用计数-1 4、对象所在容器被销毁,或者从容器中删除。
实例:
import sys a = "mark 帅哥" print(sys.getrefcount(a))
结果:
4
备注:如果实际结果与上面不符,跟使用的编辑器有很大关系,重点是理解计数引用原理,不要太在意为啥不是1.
想理解原因可以转看:https://stackoverflow.com/questions/45021901/why-does-a-newly-created-variable-in-python-have-a-ref-count-of-four
1、简单、直观 2、实时性,只要没有了引用就释放资源。
1、维护引用计数需要消耗一定的资源 2、循环应用时,无法回收。也正是因为这个原因,才需要通过标记-清理和分代收集机制来辅助引用计数机制。2、标记-清理
由上面内容我们可以知道,引用计数机制有两个缺点,缺点1还可以勉强让人接受,缺点2如果不解决,肯定会引起内存泄露,为了解决这个问题,引入了标记删除。
我们先来看个实例,从实例中领会标记删除:
a=[1,2]#假设此时a的引用为1 b=[3,4]#假设此时b的引用为1 #循环引用 a.append(b)#b的引用+1=2 b.append(a)//a的引用+1=2 假如现在需要删除a,应该如何回收呢? c=[5,6]#假设此时c的引用为1 d=[7,8]#假设此时d的引用为1 #循环引用 c.append(d)#c的引用+1=2 d.append(c)#d的引用+1=2 假如现在需要同时删除c、d,应该如何回收呢?
首先我们应该已经知道,不管上面两种情况的哪一个都无法只通过计数来完成回收,因为随便删除一个变量,它的引用只会-1,变成1,还是大于0,不会回收,为了解决这个问题,开始看标记删除来大展神威吧。
puthon标记删除时通过l两个容器来完成的:死亡容器、存活容器。 首先,我们先来分析情况2,删除c、d 删除后,c的引用为1,d的引用为1,根据引用计数,还无法删除 标记删除第一步:对执行删除操作后的每个引用-1,此时c的引用为0,d的引用为0,把他们都放到死亡容器内。把那些引用仍然大于0的放到存活容器内。 标记删除第二步:遍历存活容器,查看是否有的存活容器引用了死亡容器内的对象,如果有就把该对象从死亡容器内取出,放到存活容器内。 由于c、d都没有对象引用他们了,所以经过这一步骤,他们还是在死亡组。 标记删除第三部:将死亡组所有对象删除。 这样就完成了对从c、d的删除。
同样道理,我们来分析:只删除a的过程:
标记删除第一步:对执行删除(-1)后的每个引用-1,那么a的引用就是0,b的引用为1,将a放到死亡容器,将b放到存活容器。 标记删除第二步:循环存活容器,发现b引用a,复活a:将a放到存活容器内。 标记删除第三步:删除死亡容器内的所有对象。
综上所说,发现对于循环引用,必须将循环引用的双发对象都删除,才可以被回收。
标记-清理就是这么简单,
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/42288.html
摘要:虚拟机栈区也就是通常所说的栈区,它描述的是方法执行的内存模型,每个方法被执行的时候都创建一个栈帧,用于存储局部变量表操作数栈动态链接方法出口等。每个方法被调用到完成,相当于一个栈帧在虚拟机栈中从入栈到出栈的过程。 大多数情况下我们对GC的了解都只是浅层含义上的,下面我们来详细讲解下内部的一些实现原理。讲解GC之前,我们得先了解下JVM的内存结构,才能让我们理解GC导致是干嘛的。 一.J...
摘要:内部通过引用计数机制来统计一个对象被引用的次数。下一步,就该被我们的垃圾回收器给收走了。而我们垃圾回收机制只有当引用计数为的时候才会释放对象。以空间换时间的方法提高垃圾回收效率。 人生苦短,只谈风月,谈什么垃圾回收。据说上图是某语言的垃圾回收机制。。。我们写过C语言、C++的朋友都知道,我们的C语言是没有垃圾回...
摘要:不是引用类型,无法输出简而言之,堆内存存放引用值,栈内存存放固定类型值。变量的查询在变量的查询中,访问局部变量要比全局变量来得快,因此不需要向上搜索作用域链。 赞助我以写出更好的文章,give me a cup of coffee? 2017最新最全前端面试题 基本类型值有:undefined,NUll,Boolean,Number和String,这些类型分别在内存中占有固定的大小空...
摘要:不过不要紧,垃圾分类虽然要执行,但是奶茶也可以照喝。这里我们考虑四个类别干垃圾,湿垃圾,有害垃圾还是可回收垃圾。报纸可回收垃圾电池有害垃圾一次性餐盒干垃圾我们对图片里的物品进行分类,这是图像处理和识别的领域。 showImg(https://segmentfault.com/img/remote/1460000019671613); 目录0 环境1 引言2 思路 3 图像分类 4 总结...
阅读 3329·2023-04-26 00:07
阅读 3927·2021-11-23 10:08
阅读 2944·2021-11-22 09:34
阅读 860·2021-09-22 15:27
阅读 1750·2019-08-30 15:54
阅读 3746·2019-08-30 14:07
阅读 915·2019-08-30 11:12
阅读 681·2019-08-29 18:44