python垃圾回收机制(引用计数、循环引用、gc、标记清除、分代回收)

python垃圾回收机制(参考自https://sutune.me/

  • 概述
    • python采用的是引用计数为主,分代回收 和 标记清除 两种机制为辅的策略
  • 一、引用计数
    • python默认采用“引用计数法Reference Counting”
    • “引用计数法”原理:每个对象维护一个ob_ref字段,用来记录此对象被引用的次数
      • 当有新的引用指向时,引用计数+1
      • 当该对象的引用计数失效时,引用计数 -1
      • 一旦对象的引用计数为0,该对象立即被回收,空间将被释放
    • 引用计数案例:

https://img.mubu.com/document_image/db18378e-212f-4440-acb4-729a37646d7f-919844.jpg

    • 引用计数的漏洞
      • 让我们思考,假如,当我们产生了一种建立引用次数大于可删除引用次数的时候,就会导致这些空间永远不会被释放,那么这个时候就产生了内存泄漏。这种方式我们称之为“循环引用”
    • 循环引用案例:如下图所示,当我们在内部产生两个循环调用的时候,就算删除掉外部的两个引用,这两个实例都不会被回收机制回收,因为他们仍然存在引用

https://img.mubu.com/document_image/89a1bd80-34f5-4824-b3ad-6182c02dde28-919844.jpg

https://img.mubu.com/document_image/4eb7a1a5-5c25-43b4-9f65-9a7be0e81b47-919844.jpg

  • 二、分代回收
    • python将内存根据对象的存活时间分为不同的集合,每个集合称为一代,python将内存分为了3代。分别为 年轻代(第0代)、中年代(第1代)、老年代(第2代)
    • 这三代分别对应的是三个链表
    • 新创建的对象会被分配在年轻代。年轻代链表总数达到上限的时候,python的垃圾回收机制就会触发,把那些可以被回收的对象回收掉,而那些不会回收的对象就会被移到中年代去。以此类推,老年代中的对象是存活时间最久的对象
    • 分代回收建立在标记清除的技术基础上
  • 三、三种触发垃圾回收的情况
    • 调用gc.collect(),需要先导入gc模块
    • 当gc模块的计数器达到阈值的时候
    • 程序退出时
  • 四、gc模块
    • gc模块可以解决循环引用的问题,常用函数如下
      • gc.collect([generation])

https://img.mubu.com/document_image/73362d85-d666-4093-9e46-d06085b3c0ff-919844.jpg

        • 垃圾回收。输入参数0代表只检查第一代,输入参数1代表检查第一代和第二代,输入参数2代表检查第一、二、三代,不传的时候默认为2.
        • 返回不可达对象的数目
      • gc.get_count()

https://img.mubu.com/document_image/d391a505-6605-4bad-99d7-cb224c70ea07-919844.jpg

        • 获取当前自动执行垃圾回收的计数器,返回一个长度为3的列表
    • gc模块自动垃圾回收机制
      • 在import gc之后,设置is_enable()=True才会启动自动垃圾回收
      • 此外还有一点需要注意
        • 如果在循环引用中,两个对象都定义了__del__方法,gc模块不会销毁这些不可达对象,因为gc模块不知道应该先调用哪个对象的__del__方法,所以为了安全起见,gc模块会把对象放在gc.garbage中(这家伙是个列表)
  • 五、标记清除
    • 标记清除是一种基于追踪回收的算法,分两个阶段(下图4和5是两个非活动对象)

https://img.mubu.com/document_image/982a6633-19b8-40b9-a7e0-52096027be60-919844.jpg

      • 第一阶段,从跟对象出发,沿着有向边遍历对象,可达的对象标记为“活动对象”,不可达的对象就是要被清除的”非活动对象“
      • 第二阶段,把那些“非活动对象”进行回收
    • 标记清除主要处理一些容器对象,比如list、dict、tuple、instance等
    • 算法缺陷:操作时必须顺序扫描整个堆内存
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值