Python的垃圾回收机制

  • 引用计数

一个对象被创建完成后就有一个变量指向他,那么就说嘛他的引用计数为1,如果还有其他变量指向他,引用计数就会增加1,如果一个变量不再执行这个对象,那么这个对象的引用计数就减1。当一个对象没有任何变量指向他的时候也就是引用计数变成0的时候,那么就会被Python回收

  • 循环引用

引用计数可以解决一部分内存问题,但是还有一部分问题无法解决,即循环引用,就是a指向b,b指向a的情况

解决方法:

分代回收算法,标记清除

  • 分代回收,标记清除

在Python中,每次创建一个对象,那么就会将这个对象挂到一个零代链表中,比如以下代码:

以上代码中p1,p2,p3,p4都会被挂到一个零代链表中去p1和p2会产生循环引用,后期就算使用了del p1和del p2,这两个对象也不会得到释放,如下图

因此Python新的垃圾回收机制,如果创建的对象减去释放的对象达到了一定的值(大于等于700)那么Python就会去遍历零代链表,找到相互引用的对象,将这些对象的引用计数拷贝后减1(这叫标记清除),如果数值等于0了那么就释放这个对象,然后将剩下的没有释放的对象挪动到一个新的链表(一代链表)中

如果零代链表遍历的次数超过10次(Python默认的值),Python就会去遍历一代链表,执行和零代链表一样的操作去判断是否有循环引用,如果有,释放掉,如果还有剩下的那么就会把剩下的对象放入二代链表中。

如果一代链表遍历超过10次,就回去遍历二代链表,查找循环引用,以此类推(这叫分代回收)

关于为什么要N代链表原因:

弱代假说:新创建的对象更容易被释放,对象创建时间长了就越不容易被释放