Loading

Python的垃圾回收机制

Python的垃圾回收机制


对象:因为Python中一切皆对象,所以变量的本质其实就是对象的一个指针;比如:a = 1 其实先分配内存(创建对象)存储数据“1”;然后a变量中指向对象(变量a存储着对象的内存地址)
不可变对象:变量相对于对象的指向不会发生改变
1.具有相同值的不可变对象,变量指向的是同一个对象
2.只要不可变对象的值发生改变,变量就会指向重新创建的对象
可变对象:变量相对于对象的指向会发生改变
1.具有相同值的可变对象,变量指向的是不同的对象
2.允许可变对象存储数据的值发生改变而不影响变量的指向

因为Python运行过程中会使用各种变量,所以如果对象的占用内存管理不当,程序会由于内存溢出而异常终止


1.引用计数法

Python中采用引用计数为主,标记-清除分代回收为辅的策略

引用计数法:每当对象被引用一次引用计数就会加一;而当引用被销毁后就会进行减一,当引用计数为零时进行内存回收

优点

1.高效且易于实现
2.实时性:一旦没有引用,内存直接释放
3.对象拥有确定的周期

缺点

1.资源消耗:维护引用计数的次数和引用赋值成正比
2.无法解决循环引用问题


引用计数案例

import sys
class A():
    def __init__(self):
        '''初始化对象'''
        print('object born id:%s' %str(hex(id(self))))

def f1():
    '''循环引用变量与删除变量'''
    while True:
        c1=A()
        del c1

def func(c):
    print('obejct refcount is: ',sys.getrefcount(c)) #getrefcount()方法用于返回对象的引用计数


if __name__ == '__main__':
   #生成对象
    a=A()
    func(a)

    #增加引用
    b=a
    func(a)

    #销毁引用对象b
    del b
    func(a)

注意:查看对象的引用计数使用python内置模块中的sys的getrefcount()方法

运行结果:

object born id:0xfbfed0
obejct refcount is:  4
obejct refcount is:  5
obejct refcount is:  4

导致引用计数 +1 的情况

  • 对象被创建,例如 a=23

  • 对象被引用,例如 b=a

  • 对象被作为参数,传入到一个函数中,例如func(a)

  • 对象作为一个元素,存储在容器中,例如list1=[a,a]


导致引用计数-1 的情况

  • 对象的别名被显式销毁,例如del a

  • 对象的别名被赋予新的对象,例如a=24

  • 一个对象离开它的作用域,例如 f 函数执行完毕时,func函数中的局部变量(全局变量不会)

  • 对象所在的容器被销毁,或从容器中删除对象


2.标记-清除

标记-清除

1)它分为两个阶段:第一阶段是标记阶段,GC会把所有的活动对象打上标记,第二阶段是把那些没有标记的对象非活动对象进行回收。

2)对象之间通过引用(指针)连在一起,构成一个有向图

3)从根对象(root object)出发,沿着有向边遍历对象,可达的(reachable)对象标记为活动对象,不可达的对象就是要被清除的非活动对象,根对象就是全局变量、调用栈、寄存器。

注:像是PyIntObject、PyStringObject这些不可变对象是不可能产生循环引用的,因为它们内部不可能持有其它对象的引用。



  1. 在上图中,可以从程序变量直接访问块1,并且可以间接访问块2和3,程序无法访问块4和5
  2. 第一步将标记块1,并记住块2和3以供稍后处理。
  3. 第二步将标记块2,第三步将标记块3,但不记得块2,因为它已被标记。
  4. 扫描阶段将忽略块1,2和3,因为它们已被标记,但会回收块4和5。

3.分代回收

1、Python将内存分为了3“代”,分别为年轻代、中年代、老年代
2、最初创建对象都放在年轻代
3、当触发一次标记清除时,如果没有被清除,从年轻代到中年代
4、再一次触发标记清除,在中年代的数据依然没有被清除,就会放到老年代
5、意义:越多次数无法清除的,以后被清除的概率就更低


参考博客: https://testerhome.com/topics/16556

https://segmentfault.com/a/1190000021986557

posted @ 2021-01-26 14:08  就学45分钟  阅读(98)  评论(0编辑  收藏  举报