Created
February 20, 2021 00:51
-
-
Save miniyk2012/8678856b8c56e07ee622d6cbb912e533 to your computer and use it in GitHub Desktop.
弱引用解决循环引用的内存泄漏
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
''' | |
内存泄漏循环引用的例子 | |
https://www.jb51.net/article/200171.htm''' | |
import sys | |
import threading | |
import time | |
import gc | |
class Person(object): | |
free_lock = threading.Condition() | |
def __init__(self, name: str = ""): | |
""" | |
Parameters | |
---------- | |
name: str | |
姓名 | |
best_friend: str | |
最要好的朋友名 | |
""" | |
self._name = name | |
self._best_friend = None | |
@property | |
def best_friend(self): | |
return self._best_friend | |
@best_friend.setter | |
def best_friend(self, friend: "Person"): | |
self._best_friend = friend | |
def __str__(self): | |
return self._name | |
def __del__(self): | |
self.free_lock.acquire() | |
print(f"{self._name} 要 GG 了,现在释放它的内存空间。") | |
sys.stderr.flush() | |
self.free_lock.release() | |
def mem_leak(i): | |
""" | |
循环引用导致内存泄漏 | |
""" | |
zhang_san = Person(name='张三' + str(i)) | |
li_si = Person("李四" + str(i)) | |
# 构造出循环引用 | |
# 李四的好友是张三 | |
li_si.best_friend = zhang_san | |
# 张三的好友是李四 | |
zhang_san.best_friend = li_si | |
if __name__ == "__main__": | |
for i in range(3): | |
time.sleep(0.01) | |
print(f"{i}") | |
mem_leak(i) | |
# gc.collect() # 可以主动回收 | |
print("mem_leak 执行完成了. 由于循环引用的存在,使得, mem_leak函数就行执行完了其内部的局部变量引用计数器也不为0") | |
print('释放这部分内存有三个途径 1、 被Python的标记清除分代回收; 2、进程退出前的集中释放 3. gc.collect()主动回收') | |
time.sleep(3) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
''' | |
Python 为程序员提供了弱引用,通过这种方式可以不增加对象引用计数器的数值,这成为了我们打破循环引用的一种手段。 | |
''' | |
import sys | |
import threading | |
import time | |
import weakref | |
class Person(object): | |
free_lock = threading.Condition() | |
def __init__(self, name: str = ""): | |
""" | |
Parameters | |
---------- | |
name: str | |
姓名 | |
best_friend: str | |
最要好的朋友名 | |
""" | |
self._name = name | |
self._best_friend = None | |
@property | |
def best_friend(self): | |
return self._best_friend | |
@best_friend.setter | |
def best_friend(self, friend: "Person"): | |
self._best_friend = weakref.ref(friend) | |
def __str__(self): | |
return self._name | |
def __del__(self): | |
self.free_lock.acquire() | |
print(f"{self._name} 要 GG 了,现在释放它的内存空间。") | |
sys.stderr.flush() | |
self.free_lock.release() | |
def mem_leak(i): | |
""" | |
循环引用导致内存泄漏 | |
""" | |
zhang_san = Person(name='张三' + str(i)) | |
li_si = Person("李四" + str(i)) | |
# 构造出循环引用 | |
# 李四的好友是张三 | |
li_si.best_friend = zhang_san | |
# 张三的好友是李四 | |
zhang_san.best_friend = li_si | |
def make_friends(friend): | |
temp_friend = Person('临时人') | |
friend.best_friend = temp_friend | |
print(friend.best_friend()) | |
if __name__ == "__main__": | |
for i in range(3): | |
time.sleep(0.01) | |
print(f"{i}") | |
mem_leak(i) | |
print("mem_leak 执行完成了, 计数器清零, 就会自动释放.") | |
time.sleep(3) | |
yangkai = Person('杨恺') | |
make_friends(yangkai) | |
print(yangkai.best_friend()) # 弱引用被回收了 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment