python垃圾回收机制详解

简介: python垃圾回收机制详解

Python 是一门解释性编程语言,它的内存管理不像 C 和 C++ 一样有显式的内存分配和释放动作。Python 的内存分配和释放都是自动完成的,这往往会带来一些内存管理上的问题,如内存泄漏等。Python 的垃圾回收机制是解决这类问题的重要手段之一。

Python 的垃圾回收机制是自动的,而非强制的,Python 在解释程序执行时,使用了类似于引用计数的技术来实现垃圾回收。Python采用的是一种简单的技术:当程序中的某个变量对象引用计数为0时, Python就会将其释放掉,但这种技术会造成一些问题,比如循环引用等。因此,Python还有其他垃圾回收的方法,比如标记清除、分代回收等。

Python 的垃圾回收机制主要靠引用计数来实现。每个对象有一个引用计数,表示有多少引用指向这个对象。当引用计数降为0时,说明没有任何变量名引用这个对象了,这个对象就可以被垃圾回收器回收。垃圾回收器周期性地执行检查,以确定哪些对象已经过时,然后将它们从内存中删除。

垃圾回收机制的关键在于「引用计数」。Python 中的任何变量都是对某个对象的引用,当变量不再使用一个对象时,Python 就会减少该对象的引用计数,当引用计数降为 0 时,Python 就可以回收这个对象了。

以下是 Python 自动垃圾回收机制的原理:

1.引用计数

Python 中的一个对象对应一个结构体 PyObejct,结构体中保存了对对象所包含的数据的引用,以及引用对象的类型信息。每个对象都会统计这个对象的引用计数,引用计数要求有人来进行维护,Python 需要在代码中将这个对象打上标记,来作为引用 Python 对象的一个位置变量,在对象不再被使用时,引用计数减 1,引用计数为 0 时,释放所占的内存空间。

一般引用计数递增函数如下:

PyObject *py_incref(PyObject *op) {
    op->ob_refcnt += 1;
    return op;
}

一般引用计数递减函数如下:

void py_decref(PyObject *op) {
    op->ob_refcnt -= 1;
    if (op->ob_refcnt == 0) {
        PyObject_GC_Untrack(op);
        op->ob_type->tp_clear(op);
        op->ob_type->tp_free(op);
    }
}

引用计数的缺陷:如果对象之间存在循环引用,那么这些对象的引用计数永远不会降为 0,垃圾回收器就无法回收它们所占用的内存。对于这种情况,Python 的垃圾回收机制采用了另一个算法——标记清除算法。

2.标记清除

标记清除算法分为两个阶段:

第一阶段:标记

从根对象开始,自上而下地遍历所有对象。标记 根对象。如果一个对象没有标记,就递归地遍历这个对象所有可达的子对象,并标记。这个过程中,被标记的对象的引用计数因为被标记而增加,未被标记的对象引用计数不改变。

第二阶段:

从堆的起始地址开始,依次对每个内存地址进行遍历,对于没有被标记的对象,说明它没有被引用,可以被回收。如果一个对象被回收,那么这个对象所指向的其他对象也会被递归回收。

这样做的好处在于,标记清除算法能够解决循环引用的问题,因为只有可达的对象会被标记,不可达(孤岛)的对象永远不会被访问到,自然就不会被标记,最终被回收。但是,标记清除算法也有缺点,会产生内存碎片。

3.分代回收

Python 的垃圾回收机制中还有一种高级算法:分代回收。这个是因为,Python 中有一些对象被使用较少,有一些对象被使用较多,可以根据对象的历史使用情况把对象划分成几代。一般情况下,新创建的对象会被划分到第一代,第一代对象的存活时间较短,如果一个对象在第一代中存活了一段时间,那么它会被划分到第二代中,第二代对象的存活时间较长,同样地,如果一个对象在第二代中存活了一段时间,那么它会被划分到第三代中,第三代对象的存活时间更长。

Python 的垃圾回收机制主要运用在这三种算法之间,引用计数算法提高了回收垃圾对象的效率,标记清除算法保证了循环引用的完美处理,分代回收算法是为了增加垃圾回收的效率。

在 Python 中,可通过 sys 模块中的 getrefcount 函数来获取对象的引用计数:

import sys
variable = 'hello'
print(sys.getrefcount(variable))  #输出2,因为该函数会隐式引用变量一次

可以通过手动打印变量的引用计数来观察垃圾回收机制的工作过程:

import sys
 
class MyClass:
    def __del__(self):
        print("MyClass instance deleted")
 
def foo():
    obj = MyClass()
    print(sys.getrefcount(obj))
 
foo()

输出结果如下:

2
MyClass instance deleted

从上面的输出结果可以看出,在函数执行结束后, MyClass 实例被删除,说明垃圾回收机制已经发现并收回了这个实例对象。


从以上内容可以看出,Python 的自动垃圾回收机制是一种简单和高效的内存管理技术,它通过引用计数、标记清除以及分代回收等多种算法来管理内存分配与回收。内存管理对于编程语言来说非常重要,Python 的内存管理机制优良,使用者可以高效率地进行 Python 编程,同时也可以轻松地避免内存泄漏等不必要的麻烦。


相关文章
|
4天前
|
人工智能 Java 机器人
【python】python的垃圾回收机制(详细讲解)
【python】python的垃圾回收机制(详细讲解)
|
4天前
|
算法 Java Python
请简述Python中的垃圾回收机制。
请简述Python中的垃圾回收机制。
14 0
|
4天前
|
算法 Java Python
|
4天前
|
算法 Java 程序员
Python 基础知识: 解释 Python 的垃圾回收机制是如何工作的?
Python 基础知识: 解释 Python 的垃圾回收机制是如何工作的?
|
4天前
|
算法 Java 程序员
|
1天前
|
存储 Java 程序员
【Python 的内存管理机制专栏】深入解析 Python 的内存管理机制:从变量到垃圾回收
【5月更文挑战第18天】Python内存管理关乎程序性能与稳定性,包括变量存储和垃圾回收。变量存储时,如`x = 10`,`x`指向内存中值的引用。垃圾回收通过引用计数自动回收无引用对象,防止内存泄漏。了解此机制可优化内存使用,避免循环引用等问题,提升程序效率和稳定性。深入学习内存管理对成为优秀Python程序员至关重要。
【Python 的内存管理机制专栏】深入解析 Python 的内存管理机制:从变量到垃圾回收
|
4天前
|
监控 算法 Java
Python内存管理与垃圾回收机制
【5月更文挑战第12天】了解Python内存管理与垃圾回收对编写高效稳定程序至关重要。Python自动管理内存,使用`malloc()`和`free()`分配和释放。引用计数跟踪对象引用,当引用计数为零时对象销毁。垃圾回收处理循环引用,采用分代回收算法。优化技巧包括避免循环引用、显式释放对象、使用生成器和迭代器。理解这些机制有助于避免内存泄漏,提高性能。通过示例代码,学习如何在实践中应用内存管理最佳实践和高级优化技巧,以及如何调试和诊断内存问题。在并发和异步编程中,需注意线程安全和异步内存管理。掌握这些知识能提升Python编程的效率和质量。
17 3
|
4天前
|
算法 Java 开发者
详解python中的垃圾回收机制
详解python中的垃圾回收机制
50 0
|
4天前
|
Java 程序员 Python
|
4天前
|
算法 Java 程序员
Python内存管理:请解释Python中的引用计数机制以及如何处理循环引用。描述一下Python是如何通过垃圾回收来释放不再使用的对象内存的。
Python内存管理:请解释Python中的引用计数机制以及如何处理循环引用。描述一下Python是如何通过垃圾回收来释放不再使用的对象内存的。