Python 中的垃圾回收循环引用
Python 中的循环引用如何导致内存泄漏?GC 如何检测和清理循环引用?
回答
屠龙少年
循环引用指两个或多个对象相互引用,导致引用计数永远不为零。
class Node:
def __init__(self, name):
self.name = name
self.next = None
# 循环引用
a = Node('A')
b = Node('B')
a.next = b
b.next = a
del a, b # 引用计数不为 0,但外部无法访问
Python 的解决方案:
- 标记-清除(Mark and Sweep):GC 从根对象(全局变量、栈)出发,标记所有可达对象
- 分代回收(Generational GC):
- 第 0 代:新创建的对象
- 第 1 代:存活过一次 GC
- 第 2 代:存活过两次 GC
- 对象代数越高,GC 频率越低
import gc
print(gc.get_threshold()) # (700, 10, 10) = 第0代阈值, 第1代, 第2代
print(gc.get_count()) # 当前计数
注意:如果 __del__ 方法也形成循环引用,GC 无法回收(gc.garbage 列表中)。