首页 > 代码库 > 【Python】Python中对象管理与垃圾回收中两个很有意思的问题

【Python】Python中对象管理与垃圾回收中两个很有意思的问题

  再Python中是利用引用计数来实现对象管理和垃圾回收的,即其他对象引用该对象时候,其引用计数加1,反之减1,当引用计数为0时候,被垃圾收集器回收。

  Python解释器对对象以及计数器的管理分为以下两步:

  1)其引用计数减1

  2)判断引用计数是否为0,为0的话,销毁对象

  因为使用引用计数,造成两个问题,GIL和循环引用

一.GIL(Global Interpreter Lock)全局解释器锁

  试想一下在多线程中使用引用计数,比如线程a,b同时引用obj,那么obj的引用计数为2。

  1)当a撤销对obj的引用时候,刚做完第一步,发生线程切换,进入线程b

  2)正好b也撤销对obj的引用,obj的引用计数变为0,销毁对象,释放内存

  3)切换回线程a,a继续第二步,销毁对象。。。。结果未知

为了解决这个问题,就引入了GIL,保证对虚拟机内部共享资源的互斥性(mutex),每一时刻只有一个线程工作。如果想使用多线程的话,只有绕过GIL。。。

二.循环引用

  先看一个例子:

 1 class leak(object):
 2     def __init__(self):
 3         print("object with {0} was born".format(id(self)))
 4 
 5 while(True):
 6     A = leak()
 7     B = leak()
 8     A.b = B
 9     B.a = A
10     A = None
11     B = None

当创建的两个对象相互引用时候,即使最后把对象的两个变量指向别处,已经创建的对象的引用计数不会为0,也就不会被销毁,造成内存泄漏。。。

(我电脑跑了半天也没内存耗光。。。悲剧)

这种情况可以通过显示的调用gc.collect()进行垃圾回收

参考资料:《改善Python程序的91个建议》68、69

【Python】Python中对象管理与垃圾回收中两个很有意思的问题