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

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()

Related

How to wait for one threading to finish then run another threading

I need to open multiple chrome drivers with selenium, then execute my script by threading in them.
How to make it wait until first threading is finished and then start second threading.
time.sleep(x) wont work for me, as I do not know how much time would first threading take and I need second threading to start as soon as first one is finished.
import time
import threading
from selenium import webdriver
mydrivers=[]
tabs = []
class ActivePool(object):
def __init__(self):
super(ActivePool, self).__init__()
self.active = []
self.lock = threading.Lock()
def makeActive(self, name):
with self.lock:
self.active.append(name)
def makeInactive(self, name):
with self.lock:
self.active.remove(name)
def main_worker(s):
#Driver State
global tabs
global mydrivers
mydrivers.append(webdriver.Chrome())
tabs.append(False)
def worker(s, pool):
with s:
global tabs
global mydrivers
name = threading.currentThread().getName()
pool.makeActive(name)
x = tabs.index(False)
tabs[x] = True
mydrivers[x].get("https://stackoverflow.com")
time.sleep(15)
pool.makeInactive(name)
tabs[x]= False
for k in range(5):
t = threading.Thread(target=main_worker, args=(k,))
t.start()
# How to make it wait until above threading is finished and then start below threading
pool = ActivePool()
s = threading.Semaphore(5)
for j in range(100):
t = threading.Thread(target=worker, name=j, args=(s, pool))
t.start()
thds = []
for k in range(5):
thds.append( threading.Thread(target=main_worker, args=(k,)))
for t in thds:
t.start()
for t in thds:
t.join()
Or, even:
thds = [threading.Thread(target=main_worker, args=(k,)) for k in range(5)]
for t in thds:
t.start()
for t in thds:
t.join()
To wait for a thread to finish you should use the thread.join function. Eg...
from threading import Thread
import time
def wait_sec():
time.sleep(2)
my_thread = Thread(target=wait_sec)
my_thread.start()
# after starting the thread join it to wait for end of target
my_thread.join()
print("You have waited 2 seconds")

childthread1 wait until childthread2 complete its execution in 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()

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')

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().

Python threading. How do I lock a thread?

I'm trying to understand the basics of threading and concurrency. I want a simple case where two threads repeatedly try to access one shared resource.
The code:
import threading
class Thread(threading.Thread):
def __init__(self, t, *args):
threading.Thread.__init__(self, target=t, args=args)
self.start()
count = 0
lock = threading.Lock()
def increment():
global count
lock.acquire()
try:
count += 1
finally:
lock.release()
def bye():
while True:
increment()
def hello_there():
while True:
increment()
def main():
hello = Thread(hello_there)
goodbye = Thread(bye)
while True:
print count
if __name__ == '__main__':
main()
So, I have two threads, both trying to increment the counter. I thought that if thread 'A' called increment(), the lock would be established, preventing 'B' from accessing until 'A' has released.
Running the makes it clear that this is not the case. You get all of the random data race-ish increments.
How exactly is the lock object used?
Additionally, I've tried putting the locks inside of the thread functions, but still no luck.
You can see that your locks are pretty much working as you are using them, if you slow down the process and make them block a bit more. You had the right idea, where you surround critical pieces of code with the lock. Here is a small adjustment to your example to show you how each waits on the other to release the lock.
import threading
import time
import inspect
class Thread(threading.Thread):
def __init__(self, t, *args):
threading.Thread.__init__(self, target=t, args=args)
self.start()
count = 0
lock = threading.Lock()
def incre():
global count
caller = inspect.getouterframes(inspect.currentframe())[1][3]
print "Inside %s()" % caller
print "Acquiring lock"
with lock:
print "Lock Acquired"
count += 1
time.sleep(2)
def bye():
while count < 5:
incre()
def hello_there():
while count < 5:
incre()
def main():
hello = Thread(hello_there)
goodbye = Thread(bye)
if __name__ == '__main__':
main()
Sample output:
...
Inside hello_there()
Acquiring lock
Lock Acquired
Inside bye()
Acquiring lock
Lock Acquired
...
import threading
# global variable x
x = 0
def increment():
"""
function to increment global variable x
"""
global x
x += 1
def thread_task():
"""
task for thread
calls increment function 100000 times.
"""
for _ in range(100000):
increment()
def main_task():
global x
# setting global variable x as 0
x = 0
# creating threads
t1 = threading.Thread(target=thread_task)
t2 = threading.Thread(target=thread_task)
# start threads
t1.start()
t2.start()
# wait until threads finish their job
t1.join()
t2.join()
if __name__ == "__main__":
for i in range(10):
main_task()
print("Iteration {0}: x = {1}".format(i,x))

Categories

Resources