what does exactly the join() method do in python multithreading

Question:

I’m still learning how to use multithreading, and I’m confused about how the join() method works.
based on what I read, the join() method stops everything until the thread terminates. but take a look at this code:

from threading import Thread

def do_something(i):
    print("Sleeping...")
    time.sleep(i)
    print(f"Done sleeping {i}")

start = time.perf_counter()

t1, t2 = Thread(target=do_something, args=(1,)), Thread(target=do_something, args=(10,))

t1.start()
t2.start()

t2.join()
print("t2 joined")
t1.join()
print("t1 joined")

And when we run this, it gave us the output below:

Sleeping...
Sleeping...
Done sleeping 1
Done sleeping 10
t2 joined
t1 joined

As you can see, I used t2.join() right after starting both threads, but the first thing that got printed is Done sleeping 1. But based on what I thought join() will do, I expected t1 to be stopped, and the program gave us the output below:

Sleeping...
Sleeping...
Done sleeping 10
Done sleeping 1
t2 joined
t1 joined

Can someone explain to me what I got wrong?

Asked By: Armaho

||

Answers:

It waits for the thread to finish. That’s all it does. Nothing more, and nothing less.

Answered By: user253751

Like running multiple independent programs simultaneously, running multiple threads simultaneously also has similar features with some added benefits, which are as follows :

Multiple threads share the same data space along with the main thread within a process. Hence, they can easily share information or can communicate with each other unlike if they were processes.

Also known as light weight processes, they require less memory overhead and hence are cheaper than processes.

Multi threading is defined as the ability to execute multiple threads simultaneously or concurrently. Hence more than one thread can exists in a single process where:

Methods for Joining Threads

On invoking the join() method, the calling thread gets blocked until the thread object (on which the thread is called) gets terminated. The thread objects can terminate under any one of the following conditions

Through an ill-handled exception.
Till the optional timeout occurs or normaly

Example:

from threading import Thread
from threading import Event
import time


class Connection(Thread):

    StopEvent = 0
    
    def __init__(self,args):
        Thread.__init__(self)
        self.StopEvent = args

    # The run method is overridden to define
    # the thread body
    def run(self):

        for i in range(1,10):
            if(self.StopEvent.wait(0)):
                print ("Asked to stop")
                break;

            print("The Child Thread sleep count is %d"%(i))
            time.sleep(3)
        
        print ("A Child Thread is exiting")

Stop = Event()
Connection = Connection(Stop)       
Connection.start()
print("Main thread is starting to wait for 5 seconds")

Connection.join(5)
print("Main thread says : I cant't wait for more than 5 
seconds for the child thread;n Will ask child thread to stop")

# ask(signal) the child thread to stop
Stop.set()

# wait for the child thread to stop
Connection.join()

print("Main thread says : Now I do something else to compensate
the child thread task and exit")
print("Main thread is exiting")

Answered By: Shajin

When you join thread, it means every thread waits for the other to finish before terminating.

if you write

t2.join()
t1.join()

it means t2 and t1 are gonna wait for each other to finish before terminating (essentially "killing" the thread)

Essentially, it has to do with what we call deamon thread
Initially, in python, once a thread finished it’s job, it would terminate the whole program if it had nothing to do after.

The way to avoid that was to call .join() on every thread, which mean they would wait for every thread to finish before continuing (and potentially finishing the program)

Nowaday, thread are not deamon by default anymore (you can still make them deamon with a keyword argument).

So by default, once a thread has finished it’s task it’s gonna wait for every thread to finish before stopping.

Answered By: Sparkling Marcel

t.join() method will block the calling thread until thread t finished. I don’t know how join() implemented, but probably it use semaphore mechanism. Please look at this also. Below myJoin() method will do same job mostly like join() method of Thread class did. Below program is only simple example to understand the background

from threading import Thread,Event
from time import sleep

class MyThread(Thread):

    def __init__(self):
        Thread.__init__(self)
        self.event=Event()

    def run(self):
        try:
            for i in range(5):
                print(i)
                sleep(1)
        finally:
            self.event.set()

    def myJoin(self,timeout=None):
        self.event.wait(timeout=timeout)

t = MyThread()
t.start()

print("waiting for thread t to finish")

t.myJoin()

print("thread t finished")
Answered By: Veysel Olgun
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.