Python - Multithreading
return values from threads??? is that a thing???
- multithreading - good for IO bound tasks, can actually run concurrent when waiting on IO
- multitasking - good for CPU bound tasks async
- Global Interpreter Lock (GIL) - only allows one thread at a time
import threading
def task1(num):
print("Cube: {}" .format(num * num * num))
def print_square(num):
print("Square: {}" .format(num * num))
if __name__ =="__main__":
t1 = threading.Thread(target=task1, args=(10,))
t2 = threading.Thread(target=print_cube, args=(10,))
t1.start() # start thread
t2.start()
# some other work here
t1.join() # wait for thread to finish
t2.join()
print("Done!")
os.getpid() # get PID threading.main_thread() # get main thread object threading.main_thread().name # name of main thread threading.current_thread().name # name of current thread
ThreadPool
threads are created in advance and can be reused
import concurrent.futures
def worker():
print("Worker thread running")
pool = concurrent.futures.ThreadPoolExecutor(max_workers=2)
pool.submit(worker) # submit task to thread pool
pool.submit(worker)
# some other work here
pool.shutdown(wait=True) # wait for worker threads to finish
print("Main thread continuing to run")
””” Main Thread : The initial thread of execution when the program starts. Daemon Threads : Background threads that automatically exit when the main thread terminates. Non-Daemon Threads : Threads that continue to run until they complete their task, even if the main thread exits. “””
Synchronization
critical section - section of code that accesses shared resource “Concurrent accesses to shared resource can lead to race condition.” Lock class uses an OS semaphore
import threading
global variable x
x = 0
def increment(): “”” function to increment global variable x “”” global x x += 1
def thread_task(lock): “”” task for thread calls increment function 100000 times. “”” for _ in range(100000): lock.acquire() # Lock, blocking set to True by default increment() lock.release() # unlock, ThreadError if already unlocked
def main_task(): global x # setting global variable x as 0 x = 0
# creating a lock
lock = threading.Lock()
# creating threads
t1 = threading.Thread(target=thread_task, args=(lock,))
t2 = threading.Thread(target=thread_task, args=(lock,))
# 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))