Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python threading.Thread, scopes and garbage collection

Say I derive from threading.Thread:

from threading import Thread

class Worker(Thread):
    def start(self):
        self.running = True
        Thread.start(self)

    def terminate(self):
        self.running = False
        self.join()

    def run(self):
        import time
        while self.running:
            print "running"
            time.sleep(1)

Any instance of this class with the thread being started must have it's thread actively terminated before it can get garbage collected (the thread holds a reference itself). So this is a problem, because it completely defies the purpose of garbage collection. In that case having some object encapsulating a thread, and with the last instance of the object going out of scope the destructor gets called for thread termination and cleanup. Thuss a destructor

    def __del__(self):
        self.terminate()

will not do the trick.

The only way I see to nicely encapsulate threads is by using low level thread builtin module and weakref weak references. Or I may be missing something fundamental. So is there a nicer way than tangling things up in weakref spaghetti code?

like image 798
datenwolf Avatar asked Dec 02 '11 16:12

datenwolf


People also ask

Do threads get garbage collected?

The Thread is not garbage collected because there are references to the threads that you cannot see. For example, there are references in the runtime system. When the Thread is created it is added to the current thread group.

What happens to an execution thread when garbage collection runs?

run() will finish its execution, your current thread will sleep, and your while will continue its loop and do it over and over. The GC can hit at any point and, as others have stated, running threads (threads that were started with start() ) will only be GCed if they have finished their execution.

Does threading in python use multiple cores?

Only a single thread can acquire that lock at a time, which means the interpreter ultimately runs the instructions serially. This design makes memory management thread-safe, but as a consequence, it can't utilize multiple CPU cores at all.


1 Answers

How about using a wrapper class (which has-a Thread rather than is-a Thread)?

eg:

class WorkerWrapper:
    __init__(self):
        self.worker = Worker()
    __del__(self):
        self.worker.terminate()

And then use these wrapper classes in client code, rather than threads directly.

Or perhaps I miss something (:

like image 120
jwd Avatar answered Sep 21 '22 09:09

jwd