python中的垃圾回收机制是如何的,请坐简单的讲解,大多数面试都会问到的问题,今天我来根据我所理解的,简单给大家讲解下
垃圾回收机制
垃圾回收,主要以引用计数为主,标记清除和分代回收为辅!
这时候就牵扯到三个技术点了,引用计数,标记清除和分代回收
引用计数
每当你创建一个对象的时候,在其底层都会生成一个ob_refcnt,这个就是对象的引用计数,每次对对象引用,其引用计数都会加1
a = 1
b = a
a的引用计数就为2
当使用了 del b
就是删除一个引用计数b,此时a的引用计数就为1,当引用计数为0是就会进行垃圾回收,销毁对象,释放内存
但在引用计数中存在bug现象,也就是循环引用导致的内存泄漏问题,如何解决呢,这时候就涉及到,标记清除和分代回收了。
#循环引用代码示范 v1 = [11,22,33] v2 = [44,55,66] v1.append(v2) v2.append(v1) del v1 del v2
标记清除
标记清除就是用来解决循环引用问题,
其原理就是在python中再开辟出一块新的地址,用来存放可能出现循环引用的对象,在某种特定的情况下对可能出现问题的进行扫描,不光对原对象进行扫描检查,对其子元素进行检查,如果存在循环引用的情况,如果有,就对其引用计数减1,如果引用计数为0,就垃圾回收,如果不是0就继续放在内存中。简而言之就是循环每个对象,和对象的子元素。
在这里我提到了在某种特定的情况下就行扫描,这时候就会有两个问题!!!
1 . 在什么时候进行扫描
2 . 每次扫描的代价大
这两个问题就可以引入另外的一个话题 -----分代回收
分代回收
分代回收顾名思义,将可能出现循环引用的的对象进行分代,也就是0代,1代,2代
多久扫描一次呢?
0代:0代中的对象个数等于700个扫描一次
1代:0代中的对象扫描10次,1代扫描1次
2代:1代中的对象扫描10次,2代扫描1次
接下来简单描述一下过程——
每当有可能出现循环引用的对象时,默认加入0代,当0代中的对象个数为700时,就会对0代中的所有对象进行扫描,没有问题的加入1代,又问题的进行回收,当0代扫描次数为10时,一代就会扫描,将没有问题的放入2代,一代扫描次数为10时,二代才会进行扫描!
这就是分代回收的一个底层原理



