Python threads garbage collection

2019-06-18 20:55发布

问题:

Is a running thread eligable for garbage collection if the thread object is reasigned? For example:

class A(threading.Thread)
    def run():
        while True:
            #Do stuff


a = A()
a.start()
time.sleep(60)
a = A()

at this point, even though thread A is still doing stuff, can the interpreter destroy the original A() thread? If it does, is there a way to prevent this from happening?

回答1:

My guess is no. There's still a reference to the thread in whatever structure Python uses to keep track of things. I'll test it out, but I'd be astonished if it didn't work.

EDIT Check it out:

#!/usr/bin/env python
import threading, time

class A(threading.Thread):
    def __init__(self, name):
            threading.Thread.__init__(self)
            self.name=name
            self.count=0
    def run(self):
            while self.count<10:
                    print self.name, "Running!"
                    time.sleep(1)
                    self.count+=1

a=A("first")
a.start()
time.sleep(5)
a=A("second")
a.start()
first Running!
first Running!
first Running!
first Running!
first Running!
second Running!
first Running!
second Running!
first Running!
first Running!
second Running!
first Running!
second Running!
first Running!
second Running!
second Running!
second Running!
second Running!
second Running!
second Running!


回答2:

Threads wont get deleted like that, but I guess the problem you have is that threads disappear for no reason? A unhandled Exception will kill a thread without affecting the main thread! It only prints the traceback to stderr, but you might not see that ...



回答3:

Threads won't get garbage collected if there is a reference to the object kept somewhere.

see https://hg.python.org/cpython/file/2.7/Lib/threading.py, it keeps tabs on thread objects.

# Active thread administration
_active_limbo_lock = _allocate_lock()
_active = {}    # maps thread id to Thread object
_limbo = {}

The threading module keeps references in module variables. When you call threading.enumerate() you are iterating over the same variables.

When you call start() it inserts a reference to the Thread object in the module variable and when run() terminates, it cleans up the reference.