childthread1 wait until childthread2 complete its execution in python? - python

I want to pause the execution of t1 (thread_A) until the t2 (thread_B) complete its execution.
import threading
import time
def thread_A():
for x in range(50):
print(x)
time.sleep(0.5)
def thread_B():
for x in range(5):
print(x)
time.sleep(0.5)
if __name__ == "__main__":
t1 = threading.Thread(target=thread_A)
t1.start()
t2 = threading.Thread(target=thread_B)
t2.start()

For example, the simplest way:
...
t2 = threading.Thread(target=thread_B)
t2.start()
t2.join() # wait t2 finished
t1 = threading.Thread(target=thread_A)
t1.start()
t1.join() # wait t1 finished
As I know there is no special method to pause a thread. These should be somehow synchronized. For example, using threading.Event object:
import threading
import time
event = threading.Event()
def thread_A():
event.wait()
for x in range(50):
print(x)
time.sleep(0.5)
def thread_B():
for x in range(5):
print(x)
time.sleep(0.5)
event.set()
if __name__ == "__main__":
t1 = threading.Thread(target=thread_A)
t1.start()
t2 = threading.Thread(target=thread_B)
t2.start()

Related

Is there a way to have threads communicate with each other?

Hi I am trying to make it so 2 threads will change the other one but I can't figure it out this is an example of what I have
Import time
Import threading
s=0
def thing1():
time.sleep(1)
s+=1
def thing2():
print(s)
t = threading.Thread(target = thing1)
t.start()
t2 = threading.Thread(target = thing2)
t2.start()
When they run thing2 will print 0, not the seconds. I have it so they run later this is just all the code that's necessary
You need to use a semaphore so that each thread is not accessing the variable at the same time. However, any two threads can access the same variable s using global.
import threading
import time
s = 0
sem = threading.Semaphore()
def thing1():
global s
for _ in range(3):
time.sleep(1)
sem.acquire()
s += 1
sem.release()
def thing2():
global s
for _ in range(3):
time.sleep(1)
sem.acquire()
print(s)
sem.release()
t = threading.Thread(target = thing1)
t.start()
t2 = threading.Thread(target = thing2)
t2.start()

Thread is not printing properly

I can't seem to bring multithreading to work.
I simplified my problem and I still can't get my threads to print properly (so I guess they're not executing correctly).
import time, threading
s_print_lock = threading.Lock()
def s_print(*a, **b):
with s_print_lock:
print(*a, **b)
# Thread safe print function
def a():
while True:
s_print('\'a\' is running')
time.sleep(5)
# Thread 1
def b():
while True:
s_print('\'b\' is running')
time.sleep(5)
# Thread 2
if __name__ == "__main__":
t1 = threading.Thread(target=a())
t2 = threading.Thread(target=b())
t1.start()
t2.start()
And the output is:
'a' is running
'a' is running
'a' is running
'a' is running
...
The target must be a callable. You are executing a() so it's getting in the while True loop and never ending, so never starting the thread. Try this:
if __name__ == "__main__":
t1 = threading.Thread(target=a)
t2 = threading.Thread(target=b)
t1.start()
t2.start()

Python Threading Self Calling Threads Unexpected Behavior

I am testing a method to run several tasks in parallel. These tasks will run in parallel threads and I want the tasks to repeat until a global variable is set. I am first trying threading to launch the parallel threads, and make sure they will work properly. What I have so far:
import threading
from IPython.display import clear_output
import time
i = 0
j = 0
def main():
global i
global j
t1 = threading.Thread(name = "task1", target = task1)
t2 = threading.Thread(name = "task2", target = task2)
t1.start()
t2.start()
def task1():
global i
i += 1
time.sleep(10)
t1 = threading.Thread(name = "task1", target = task1)
t1.start()
def task2():
global j
j -= 1
time.sleep(10)
t2 = threading.Thread(name = "task2", target = task2)
t2.start()
tmain = threading.Thread(name = "main", target = main)
tmain.start()
which starts a main thread that then starts two threads which run task1 and task2. To monitor the current threads and the values of i and j I run:
while(True):
clear_output(wait=True)
for thread in threading.enumerate():
print(thread)
print(i)
print(j)
time.sleep(0.1)
(all of this is being run in a Jupyter Notebook).
Running the script above, i noticed some unexpected results. I expect that at any given time, there should be at most two threads of task1 and task2, but instead I observe many more threads of task2 compared to task1. These are not ghost or finished threads, because the absolute values of i and j grow disproportionately. Two observations I made:
Again, i expect that there should be a symmetric number of threads for both task1 and task 2, and I also expect that the abslute values of i and j should grow more proportionately than they are. Any insight on how to mitigate this discrepancy or avoid this issue would be appreciated.
I ran your code in Jupyter and didn't have your problem.
<_MainThread(MainThread, started 139735228168000)>
<Thread(Thread-1, started daemon 139735083251456)>
<Heartbeat(Thread-2, started daemon 139735074858752)>
<HistorySavingThread(IPythonHistorySavingThread, started 139735049680640)>
<Thread(task2, started 139734638634752)>
<Thread(task1, started 139734680598272)>
<Thread(task2, started 139735041287936)>
<Thread(task1, started 139734076618496)>
<Thread(task1, started 139735032895232)>
<Thread(task2, started 139734672205568)>
<Thread(task1, started 139734655420160)>
<Thread(task2, started 139734630242048)>
272
-272
But as you already saw with your own code, there are multiple instances of each task running. So after a task 'has started itself anew' it takes some time before it kills itself.
A solution to your Jupyter problem could be to give the main function the control of restarting a killed tasked. This ensures that always only 1 thread of each task is running.
import threading
from IPython.display import clear_output
import time
i = 0
j = 0
main_stop = False
def task1():
global i
i += 1
time.sleep(4)
def task2():
global j
j -= 1
time.sleep(4)
def main():
global i
global j
t1 = threading.Thread(name="task1", target=task1)
t2 = threading.Thread(name="task2", target=task2)
t1.start()
t2.start()
while not main_stop:
if not t1.is_alive():
del t1
t1 = threading.Thread(name="task1", target=task1)
t1.start()
if not t2.is_alive():
del t2
t2 = threading.Thread(name="task2", target=task2)
t2.start()
# wait for tasks to complete
while t1.is_alive():
time.sleep(0.1)
while t2.is_alive():
time.sleep(0.1)
tmain = threading.Thread(name="main", target=main)
tmain.start()
run_time = 30 # seconds
end_time = time.time() + run_time
while time.time() < end_time:
clear_output(wait=True)
for thread in threading.enumerate():
print(thread)
print(i)
print(j)
time.sleep(0.1)
main_stop = True
# wait for main to complete
while tmain.is_alive():
time.sleep(0.1)
print('program completed')

python thread.join() not join to caller thread but to another assigned thread?

python code:
import threading
def f1():
#long looping
def f2():
#another long looping
t1 = threading.Thread(target=f1)
t2 = threading.Thread(target=f2)
t1.start()
t2.start()
#t2.join(t1) <---???
Is that possible in main thread to call something like t2.join(t1)?
Understanding that I can call t2.join() from f1(), but I am seeking an way calling from external(not in t1 and t2).
Thank you.
No, you cant specify a thread in the join method.
If you want to wait for both t1 and t2 to complete before continuing execution in the main thread, join both threads:
import threading
import time
def f1():
#long looping
def f2():
#another long looping
t1 = threading.Thread(target=f1)
t2 = threading.Thread(target=f2)
t1.start()
t2.start()
t1.join()
t2.join()
print("Continuing with main thread...")

introspect current thread in python

How can one instrospect to receive the current thread object?
Consider this somewhat artificial code snippet. The use case is different, but for the sake of simplicity, I've boiled it down the the essential bit
t1 = threading.Thread(target=func)
t2 = threading.Thread(target=func)
marked_thread_for_cancellation = t1
t1.start()
t2.start()
def func():
if [get_thread_obj] is marked_thread_for_cancellation: # <== introspect here
return
# do something
You can use thread.get_ident function. Compare thread.get_ident() with Thread.ident as follow:
import thread
import threading
import time
marked_thread_for_cancellation = None
def func(identifier):
while threading.get_ident() != marked_thread_for_cancellation:
time.sleep(1)
print('{} is alive'.format(identifier))
print('{} is dead'.format(identifier))
t1 = threading.Thread(target=func, args=(1,))
t2 = threading.Thread(target=func, args=(2,))
t1.start()
t2.start()
time.sleep(2)
marked_thread_for_cancellation = t1.ident # Stop t1
In Python 3, use threading.get_ident.
You can also use your own identifier instead of thread.get_ident:
import threading
import time
marked_thread_for_cancellation = None
def func(identifier):
while identifier != marked_thread_for_cancellation:
time.sleep(1)
print('{} is alive'.format(identifier))
print('{} is dead'.format(identifier))
t1 = threading.Thread(target=func, args=(1,))
t2 = threading.Thread(target=func, args=(2,))
t1.start()
t2.start()
time.sleep(2)
marked_thread_for_cancellation = 1 # Stop t1 (`1` is the identifier for t1)
To make minimal changes to your code, here is probably what you are after:
import threading
def func():
if threading.current_thread() is marked_thread_for_cancellation: # <== introspect here
print 'cancel'
else:
print 'otherwise'
t1 = threading.Thread(target=func)
t2 = threading.Thread(target=func)
marked_thread_for_cancellation = t1
t1.start()
t2.start()
But I do not understand what do you mean by introspection. marked_thread_for_cancellation is shared by all threads, all threads have by their own is some local data, accessible via threading.local().

Categories

Resources