线程如何共享对实例的引用?

时间:2018-10-02 23:09:45

标签: python

我试图通过运行一些示例来围绕Python多线程,这是我不太了解的行为

#!python3.6

import threading
import time

class ThreadClass():

    def __init__(self):
        self.thread = threading.Thread(target=self.callback)
        self.thread.start()

    def __del__(self):
        print("DESTROYED")


    def callback(self):
        print("start second thread")
        print("second threadId=", threading.get_ident())
        print("self memory=", id(self))
        time.sleep(2)
        print("stop second thread")


def run():
    print("start first thread")
    print("first threadId=", threading.get_ident())
    thread = ThreadClass()
    print("threadClass memory=",id(thread))
    print("stop first thread")

run()
print("end")

我得到的输出是:

start first thread
first threadId= 140301467088640
start second thread
second threadId= 140301462193920
self memory= 140301465746680
threadClass memory= 140301465746680
stop first thread
end
stop second thread
DESTROYED

我不明白的是为什么run()函数结束后ThreadClass实例不被销毁。我的理解是ThreadClass的实例位于run()的堆栈上,所以当run()结束时,是否应该清除其堆栈并删除实例?但是不知何故,该ThreadClass的相同实例仍然有效,直到用它完成内存中其他地方的另一个线程为止。

换句话说,Python如何在线程之间共享内存?

2 个答案:

答案 0 :(得分:2)

运行中的线程(及其对象)永远不会被垃圾回收(守护进程线程可能会终止其进程,但那是另外一回事)。

第二个线程的运行线程对象(存储在thread实例的ThreadClass中)引用了callback实例的ThreadClass方法(因为此方法在线程),因此在线程运行时需要实例。

变量仅包含对对象的引用,而不包含对象本身。仅当不再存在对对象的引用(弱引用除外)时,才可以对其进行垃圾回收。

run()的末尾,仅从堆栈中删除了一个引用。

答案 1 :(得分:0)

注意def run()与您的代码相同,与类ThreadClass 不相关。检查您的缩进,注意run是在类之外的模块级别定义的。

按原样在代码中启动第二个线程,而不必等待它完成。因此,正常程序(run()原样运行)到最后,而(第二个)线程仍在运行。对此没什么奇怪的,这就是为什么要使用线程的原因。并行运行并异步运行。

此外,为了获得完整的响应,python不保证立即进行垃圾回收。如果不再引用变量,则没有任何东西可以立即释放内存,任何句柄等。 因此,线程可能不会停止存在(并正在运行),可能直到整个python环境完成为止。 例如放在Thread garbage collection中,模块线程将保留对线程的引用。