Python3循环引用还是会自动垃圾回收的。

以前都听说Python循环引用会导致引用数无法清零,所以不能垃圾回收,会内存泄漏,需要删除引用关系或者用gc.collect()才能进行正常垃圾回收。

但做了下实验,好像还是会自动回收循环引用的变量,在约44对循环引用变量时会首次清理,之后大约每产生200对的垃圾就会清一次,但也没清干净,总是会有残留上几个,而且听说了改__del__会影响垃圾回收,实质上也不会影响。

进程内存监控,可以看出内存大小基本没变,还是符合认知的。

====运行环境====

win10 1903
Python 3.7.5 64bit

=====代码=====

import psutil

class A:
    t = 0
    def __del__(self):
        A.t += 1

class B:
    t = 0
    def __del__(self):
        B.t += 1

if __name__ == '__main__':
    pid = os.getpid()
    at, bt = 0, 0
    for i in range(10000):
        a, b = A(), B()
        a.b, b.a = b, a
        #del a, b
        if A.t != at or B.t != bt:
        print(f'No_{i}: (d_i: {i - at}, d_a: {A.t - at}, d_b: {B.t - bt})')
        print('Used Memory:', psutil.Process(pid).memory_info().rss / 1024 / 1024, 'MB')
        at, bt = A.t, B.t

====打印结果====

No_44: (d_i: 44, d_a: 43, d_b: 43)
Used Memory: 13.69921875 MB
No_236: (d_i: 193, d_a: 190, d_b: 190)
Used Memory: 13.8046875 MB
No_431: (d_i: 198, d_a: 193, d_b: 193)
Used Memory: 13.8046875 MB
No_626: (d_i: 200, d_a: 194, d_b: 194)
Used Memory: 13.8046875 MB
No_822: (d_i: 202, d_a: 194, d_b: 194)
Used Memory: 13.8046875 MB
No_1017: (d_i: 203, d_a: 194, d_b: 194)
Used Memory: 13.8046875 MB
No_1212: (d_i: 204, d_a: 193, d_b: 193)
Used Memory: 13.8046875 MB
No_1407: (d_i: 206, d_a: 194, d_b: 194)
Used Memory: 13.8046875 MB
No_1603: (d_i: 208, d_a: 194, d_b: 194)
Used Memory: 13.8046875 MB
No_1798: (d_i: 209, d_a: 194, d_b: 194)
Used Memory: 13.8046875 MB
No_1993: (d_i: 210, d_a: 193, d_b: 193)
Used Memory: 13.8046875 MB
No_2188: (d_i: 212, d_a: 212, d_b: 212)
Used Memory: 13.8046875 MB
No_2384: (d_i: 196, d_a: 194, d_b: 194)
Used Memory: 13.8046875 MB
No_2579: (d_i: 197, d_a: 194, d_b: 194)
Used Memory: 13.8046875 MB
No_2774: (d_i: 198, d_a: 193, d_b: 193)
Used Memory: 13.8046875 MB
No_2969: (d_i: 200, d_a: 194, d_b: 194)
Used Memory: 13.8046875 MB
No_3165: (d_i: 202, d_a: 194, d_b: 194)
Used Memory: 13.8046875 MB
No_3360: (d_i: 203, d_a: 194, d_b: 194)
Used Memory: 13.8046875 MB
No_3555: (d_i: 204, d_a: 193, d_b: 193)
Used Memory: 13.8046875 MB
No_3750: (d_i: 206, d_a: 194, d_b: 194)
Used Memory: 13.8046875 MB
No_3946: (d_i: 208, d_a: 194, d_b: 194)
Used Memory: 13.8046875 MB
No_4141: (d_i: 209, d_a: 194, d_b: 194)
Used Memory: 13.8046875 MB
No_4336: (d_i: 210, d_a: 193, d_b: 193)
Used Memory: 13.8046875 MB
No_4531: (d_i: 212, d_a: 211, d_b: 211)
Used Memory: 13.8046875 MB
No_4727: (d_i: 197, d_a: 194, d_b: 194)
Used Memory: 13.8046875 MB
No_4922: (d_i: 198, d_a: 194, d_b: 194)
Used Memory: 13.8046875 MB
No_5117: (d_i: 199, d_a: 193, d_b: 193)
Used Memory: 13.8046875 MB
No_5312: (d_i: 201, d_a: 194, d_b: 194)
Used Memory: 13.8046875 MB
No_5508: (d_i: 203, d_a: 194, d_b: 194)
Used Memory: 13.8046875 MB
No_5703: (d_i: 204, d_a: 194, d_b: 194)
Used Memory: 13.8046875 MB
No_5898: (d_i: 205, d_a: 193, d_b: 193)
Used Memory: 13.8046875 MB
No_6093: (d_i: 207, d_a: 194, d_b: 194)
Used Memory: 13.8046875 MB
No_6289: (d_i: 209, d_a: 194, d_b: 194)
Used Memory: 13.8046875 MB
No_6484: (d_i: 210, d_a: 194, d_b: 194)
Used Memory: 13.8046875 MB
No_6679: (d_i: 211, d_a: 193, d_b: 193)
Used Memory: 13.8046875 MB
No_6874: (d_i: 213, d_a: 211, d_b: 211)
Used Memory: 13.8046875 MB
No_7070: (d_i: 198, d_a: 194, d_b: 194)
Used Memory: 13.8046875 MB
No_7265: (d_i: 199, d_a: 194, d_b: 194)
Used Memory: 13.8046875 MB
No_7460: (d_i: 200, d_a: 193, d_b: 193)
Used Memory: 13.8046875 MB
No_7655: (d_i: 202, d_a: 194, d_b: 194)
Used Memory: 13.8046875 MB
No_7851: (d_i: 204, d_a: 194, d_b: 194)
Used Memory: 13.8046875 MB
No_8046: (d_i: 205, d_a: 194, d_b: 194)
Used Memory: 13.8046875 MB
No_8241: (d_i: 206, d_a: 193, d_b: 193)
Used Memory: 13.8046875 MB
No_8436: (d_i: 208, d_a: 194, d_b: 194)
Used Memory: 13.8046875 MB
No_8632: (d_i: 210, d_a: 194, d_b: 194)
Used Memory: 13.8046875 MB
No_8827: (d_i: 211, d_a: 194, d_b: 194)
Used Memory: 13.8046875 MB
No_9022: (d_i: 212, d_a: 193, d_b: 193)
Used Memory: 13.8046875 MB
No_9217: (d_i: 214, d_a: 211, d_b: 211)
Used Memory: 13.8046875 MB
No_9413: (d_i: 199, d_a: 194, d_b: 194)
Used Memory: 13.8046875 MB
No_9608: (d_i: 200, d_a: 194, d_b: 194)
Used Memory: 13.8046875 MB
No_9803: (d_i: 201, d_a: 193, d_b: 193)
Used Memory: 13.8046875 MB
No_9998: (d_i: 203, d_a: 194, d_b: 194)
Used Memory: 13.8046875 MB

====实验结束====

之前了解Python3的print是线程安全的,但在这个垃圾回收的实验里,如果在__del__函数里添加print,在自动回收垃圾时有一定概率(概率小于20%)报出非阻塞的错误。
不过似乎只在Power shell会报错,在cmd里似乎不会报错,但考虑到cmd的输出远快于Power shell,可能是达不到并发标准所以在cmd才不报错。
而且是在此期间所有同时被回收的对象都会同时报错,还不太了解什么原因,不知道是不是并发回收对象的问题。

报错信息如下,一般一出就是4百条同时来:

RuntimeError: reentrant call inside <_io.BufferedWriter name='<stdout>'>

 

================================

其实原因还是很清楚的,就是不可重入,和线程安全是两回事。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值