垃圾回收机制
Python解释器自带一种机制,其实高级的语言大多数都有自己的垃圾回收机制简称GC,专门用来回收不可用的变量值所占用的内存空间
为什么需要垃圾回收
如果不进行垃圾回收,内存迟早都会被消耗空,因为我们在不断的分配内存空间而不进行回收。除非内存无限大,我们可以任性的分配而不回收,但是事实并非如此。所以,垃圾回收是必须的。
python当中主要通过三种方式解决垃圾回收(引用计数,标记清除,分代回收)
引用计数
直接引用指的是从栈区出发直接引用到的内存地址。 间接引用指的是从栈区出发引用到堆区后,再通过进一步引用才能到达的内存地址。 引用计数(数据值身上直接(名字绑定)或者间接(数据相互绑定)被引用的次数,如果有新的引用指向对象,对象引用计数就加1,引用被销毁时,对象引用计数减1。当引用计数为0就会被垃圾回收机制清除) 但是有个问题:循环引用(比如两个列表相互追加) '循环引用'会导致:值不再被任何名字关联,但是值的引用计数并不会为0,应该被回收但没有被回收
标记/清除
为了解决循环引用带来的内存泄漏问题, 将内存中程序产生的所有数据值全部检查一遍,先标记出所有需要回收的对象,标记完成后统一回收所有被标记的对象。 核心:一个变量值没有任意一条可以从栈区出发到自己的引用,就会被标记下来,方便后续清除 这种做法的不足主要体现在效率和空间,从效率的角度讲,标记和清除两个过程的效率都不高;从空间的角度讲,标记清除后会产生大量不连续的内存碎片, 内存碎片太多可能会导致以后程序运行过程中在需要分配较大对象时,无法找到足够的连续内存而不得不提前触发一次垃圾收集动作。 首先初始所有对象标记为白色,并确定根节点对象(这些对象是不会被删除),标记它们为黑色(表示对象有效)。 将有效对象引用的对象标记为灰色(表示对象可达,但它们所引用的对象还没检查),检查完灰色对象引用的对象后, 将灰色标记为黑色。重复直到不存在灰色节点为止。最后白色结点都是需要清除的对象
分代回收
分代指的是根据存活时间来为变量划分不同等级(也就是不同的代),回收依然是使用引用计数作为回收的依据 个别垃圾有可能得不到及时的清理,标记清除每隔一段时间就需要将所有的数据排查一遍资源消耗过大,为了解决'引用计数的效率问题',为了减轻垃圾回收机制的资源损耗,开发了三代管理,越往下检测的频率越低