What is the Join() function for in the threading module?

Asked

Viewed 144 times

6

I’ve seen the function join() for the module threading, but I didn’t quite understand what she does.

1 answer

9

The .join simply pause the current thread (from where it was called) until the target thread (the thread it is attached to) ends.

It is a way to re-sync the program, ensuring that no parallel processing is taking place.

What he nay does is the most important: it does not transmit any signal, make any request, or cause the target thread to be terminated. The program keeps running normally, the target thread continues its processing - and when it is terminated, the Join function returns.

In other words, the call minhathread.join() is the equivalent of "pause the program here and wait for the minhathread to finish".

If you need a way to warn another thread that it should end, you have to take a look at the thread events and queues - and your code that runs in the thread has to look at those messages and end the execution. In Python there is no way for an external signal to terminate a running thread without its code predicting it. (in other languages also there is no safe way to do this, only "violent stops")

The Join method also accepts a timeout parameter in seconds: it is the maximum time the execution will wait for the other thread to close - after that time the call returns, and you have to check if the target thread is still active by calling the method .is_alive hers.

Below, I make a joke with two threads in an interactive session, and demonstrate the use of a "threading.Event" object to stop a thread, and "Join" in a second thread waiting for the end of the first:


In [227]: import threading        

In [228]: evento = threading.Event()                                 

In [229]: def contador(): 
     ...:     i = 0 
     ...:     while True: 
     ...:         parar_agora = evento.wait(1) 
     ...:         if parar_agora: 
     ...:             break 
     ...:         i += 1 
     ...:         print(i) 
     ...:                         

In [230]: def espera_contador(t): 
     ...:     t.join() 
     ...:     print("O contador parou") 
     ...:                         

In [231]: t1 = threading.Thread(target=contador); t2 = threading.Thread(target=lambda: espera_contador(t1))                               

In [232]: t1.start(); t2.start() 
     ...:                         

1
2
3
4
5
6
In [233]: evento.set()            

O contador parou

(The use of lambda in lambda: espera_contador(t1) was made to pass the parameter "t1" for the call, since "target" does not accept parameters - then I remembered that I could have used the parameter "args" when creating the thread: t1 = threading.Thread(target=contador); t2 = threading.Thread(target=espera_contador, args=[t1]))

  • Thanks, thanks for the explanation.

  • Remembering that it should be called Join() for all threads, even if they have already stopped. Calling Join() frees up system resources, similar to Wait() for processes. A thread is a "lightweight process" and the system stores its state until someone calls Join() to read that state.

  • yes - if you are designing a long-running app that uses threads, with low-level implementation using threading, accurate. I think 90% of what is written using threading are "one shot" scripts - it’s over, it ends the process (there’s good Join to make sure everything is finished). Other uses encapsulate thread creations and signals between them in higher-level constructions (e.g. Concurrent.) .

Browser other questions tagged

You are not signed in. Login or sign up in order to post.