Python24 min read

Python Threading Basics

Learn threading step by step: starting threads, joining, shared state, and using locks to avoid race conditions.

Michael Brown
August 12, 2025
3.9k118

Threading lets your program run tasks “at the same time” (concurrently). It is most useful when tasks are waiting on I/O, like:
- downloading files
- making API requests
- reading/writing files
- waiting for network responses

  Important concept:
  Threads in Python are not best for CPU-heavy tasks due to the GIL. For CPU-heavy workloads, `multiprocessing` is usually better.
  
  ## Basic thread example
  
  ```python
  import threading
  import time
  
  def task(name):
      print(f"{name} starting...")
      time.sleep(2)
      print(f"{name} done!")
  
  t1 = threading.Thread(target=task, args=("Task 1",))
  t2 = threading.Thread(target=task, args=("Task 2",))
  
  t1.start()
  t2.start()
  
  t1.join()
  t2.join()
  
  print("All done!")
  ```
  
  Expected output (order may vary slightly):
  
  ```
  Task 1 starting...
  Task 2 starting...
  Task 1 done!
  Task 2 done!
  All done!
  ```
  
  ## Threading with a list of tasks
  
  ```python
  import threading
  import time
  
  def download_file(file_name):
      print(f"Downloading {file_name}...")
      time.sleep(1)
      print(f"Downloaded {file_name}")
  
  files = ["file1.txt", "file2.txt", "file3.txt"]
  threads = []
  
  for file in files:
      t = threading.Thread(target=download_file, args=(file,))
      t.start()
      threads.append(t)
  
  for t in threads:
      t.join()
  
  print("All downloads finished.")
  ```
  
  ## Shared data problem (race condition)
  
  If multiple threads update the same variable, results can be wrong.
  
  ## Fix with Lock
  
  ```python
  import threading
  
  counter = 0
  lock = threading.Lock()
  
  def increment():
      global counter
      for _ in range(100000):
          with lock:
              counter += 1
  
  threads = [threading.Thread(target=increment) for _ in range(10)]
  
  for t in threads:
      t.start()
  
  for t in threads:
      t.join()
  
  print(counter)
  ```
  
  Expected output:
  
  ```
  1000000
  ```
  
  ## Graph: thread lifecycle
  
  ```mermaid
  flowchart TD
    A[Create Thread] --> B[start()]
    B --> C[Run task]
    C --> D[join()]
    D --> E[Program continues]
  ```
  
  In the next lesson, you will learn how to work with APIs in Python, which is a practical skill for building real applications.
#Python#Intermediate#Threading