一个由引用计数引起的Python内存管理小瑕疵

这个代码是在看了“码农高天”的视频照模仿的。

Python 的垃圾回收(Garbage Collection,以下简称 GC)算法是基于引用计数的方式实现的,即 Python 不会记录一个变量被哪几个变量所引用(函数也可以理解为一种变量),只会标记一个变量被引用了多少次
这种策略可以以极低的性能成本实现内存的自动回收功能,常在退出函数调用时使用,用于销毁其引用的所有变量。

这种策略虽然大幅增强 GC 算法的性能,但是一旦出现变量间的相互引用现象(即存在环路),那么基于引用计数的 GC 算法将无法有效识别出无用变量。也就无法实现实时的变量销毁功能。

以下是一段测试 GC 算法的样例代码,其中 __del__ 是 Python 定义的一个魔术方法,当一个对象将要被销毁时,GC 会自动调用该方法。该魔术方法常用于释放预先设置的系统资源。我们可以通过该魔术方法来观察对象何时被销毁。

from typing import Any, Optional
import gc


class Object:
    def __init__(self, name: str) -> None:
        self.obj: Optional[Any] = None
        self.name: str = name

    def __del__(self):
        print(f"{self.name} is deleted")


def main():
    a = Object("A")
    b = Object("B")

    a.obj = b
    b.obj = a


if __name__ == "__main__":
    main()
    print("start Garbage Collection")
    gc.collect()
    print("program end")

main 函数执行完成后,可以看到两个声明的变量A和B并没在main函数执行完成后销毁,而是在调用了 gc.collect() 之后才成功销毁。如下图所示:

实际上为了解决这一问题,Python还引入了循环垃圾检测(Cycle Detection)算法用于解决此类问题。该算法将会从根对象(全局变量容器)开始扫描并标记是否引用,然后再统一清除未引用的变量。不过由于该算法性能开销较大,因此触发该算法的条件较为苛刻,如使用内存快满了或手动调用 gc.collect() 时才会开始扫描。
分代回收算法则是循环垃圾检测的一种补充算法,在降低了性能开销的前提下,显著提升了垃圾回收效率。

来源链接:https://www.cnblogs.com/somata/p/18698452

© 版权声明
THE END
支持一下吧
点赞11 分享
评论 抢沙发
头像
请文明发言!
提交
头像

昵称

取消
昵称表情代码快捷回复

    暂无评论内容