Search code examples
pythonmultithreadingconcurrencyparallel-processingpython-multithreading

Unexpected behavior of Threading.join() - Code between calls to Threading.join()


Does the order of the Threading.join()s in the source code GUARANTEE the order of execution of the threads OR IS IT SIMPLY to ensure that the main thread finishes UNTIL ALL THREADS FINISH?

import threading, time

class myThread(threading.Thread):
    def __init__(self, threadID, name, duerme):
        super(myThread, self).__init__()
        self.threadID = threadID
        self.name = name
        self.duerme = duerme

    def run(self):
        print("run()", self.name)
        time.sleep(self.duerme)
        print("%s termino " % self.name)


thread1 = myThread(1, "Thread-1", 20)
thread2 = myThread(2, "Thread-2", 12)
thread3 = myThread(3, "Thread-3", 6)

thread2.start()
thread1.start()
thread3.start()

thread3.join()
thread1.join()
thread2.join()

print("termino el hilo principal")

output:

run() Thread-2
run() Thread-1
run() Thread-3
Thread-3 termino
Thread-2 termino
Thread-1 termino
termino el hilo principal

If so, Can I see it as a "hook" (telling me that the code below the join()s is sure to be executed AFTER THREADS END ) that simply tells me when threads end?

If I put code between join()s (I change the last part):

thread3.join()
print("debajo del thread3")
thread1.join()
print("debajo del thread1")
thread2.join()
print("debajo del thread2")

print("termino el hilo principal")

I get this:

run() Thread-2
run() Thread-1
run() Thread-3
Thread-3 termino
debajo del thread3
Thread-2 termino
Thread-1 termino
debajo del thread1
debajo del thread2
termino el hilo principal

it is as if the phrase "debajo del thread2" WAS waiting for thread1.

Expected output:

run() Thread-2
run() Thread-1
run() Thread-3
Thread-3 termino
debajo del thread3
Thread-2 termino
debajo del thread2
Thread-1 termino
debajo del thread1
termino el hilo principal

Solution

  • Does the order of the Threading.join()s in the source code GUARANTEE the order of execution of the threads

    Which threads are you asking about? If you are asking about order of execution of thread1, thread2, and thread3, then then answer is, absolutely NOT. When you call t.join() it does not do anything at all to thread t. IMO, the best way to think of join is, it does nothing, and it keeps doing nothing until thread t has finished, and then it returns.

    OTOH, if you are asking about your main thread, then yes, when your main thread calls threadN.join(), then your main thread will be "blocked" until threadN is finished.

    ...order of execution of the threads...

    Your thread1, thread2, and thread3 are completely unsynchronized. They run concurrently.* "Concurrency" means there are no guarantees about which thread does what, when unless they do something that explicitly synchronizes them.

    An example of explicit synchronization would be if one thread releases a mutex that some other thread is waiting for. The thread that is waiting for the mutex is guaranteed not to proceed until the first thread releases it.

    Another example of something that synchronizes threads is join. When thread A joins thread B, then thread A is guaranteed not to proceed until after thread B has ended.


    * Doing things concurrently is the entire point of using threads. If you don't want concurrency, then don't use threads.