Python Threading
In this page:
import threading
thread = threading.Thread(target=function_name, args=(arg,))
thread.start()
thread.join()
What is Threading?
Threading lets a program run multiple pieces of code seemingly at the same time within one process, which is most useful for I/O-bound tasks (waiting on network requests or disk reads) where a thread can idle without blocking the rest of the program -- CPU-bound work benefits far less due to Python's GIL.
Example: What is Threading?
import threading
print(threading.active_count())
Creating a Basic Thread
Creating a thread means instantiating threading.Thread(target=some_function) and then calling .start() on it -- start() launches the thread running concurrently with the rest of your program, rather than running it immediately and blocking like a normal function call would.
Example: Creating a Basic Thread
import threading
def task():
print("Running in a thread")
t = threading.Thread(target=task)
t.start() # starts running concurrently
t.join() # waits for the thread to finish
Joining Threads
By default, your main program keeps executing immediately after start() without waiting for the thread to finish -- calling .join() on a thread object blocks the calling code until that specific thread has completed, which matters when later code depends on the thread's work being done.
Example: Joining Threads
import threading
def task():
print("Thread work done")
t = threading.Thread(target=task)
t.start()
t.join() # blocks here until the thread completes
print("Main continues after thread finishes")
Threading with Arguments
The args parameter to Thread() accepts a tuple of arguments to pass into the target function when the thread starts -- Thread(target=download, args=(url,)) is how you launch download(url) to run concurrently rather than calling it directly.
Example: Threading with Arguments
import threading
def greet(name):
print("Hello,", name)
t = threading.Thread(target=greet, args=("Alex",)) # args are passed to greet when the thread starts
t.start()
t.join()
Thread Safety and Locks
Because threads in the same process share memory, two threads modifying the same variable at the same moment can corrupt it through a race condition -- threading.Lock() lets you mark a section of code so only one thread can execute it at a time, preventing that kind of collision.
Example: Thread Safety and Locks
import threading
counter = 0
lock = threading.Lock()
def increment():
global counter
with lock: # only one thread runs this block at a time
counter += 1
threads = [threading.Thread(target=increment) for _ in range(5)]
for t in threads:
t.start()
for t in threads:
t.join()
print(counter)
- Calling
t.run()instead oft.start(), which runs the function in the current thread and not a new one. - Writing
Thread(target=work()), which calls the function right away; passtarget=workinstead. - Updating a shared variable from several threads without a
Lock, which causes race conditions.
Chapter Quiz — Complete all 12 topics to unlock
0/12 topics done
Complete these topics first: