How to Pause and Resume Threads with threading.Event in Python

Use threading.Event to pause and resume worker threads in Python, controlling execution flow with set and clear methods.

Medium Python 3.9+ Aug 9, 2026 Concurrency & performance 11 views 0 copies

Python code

48 lines
Python 3.9+
import threading
import time

workers = []

def worker(name, event):
    for i in range(10):
        event.wait()
        print(f"{name} step {i}")
        time.sleep(0.1)

def pause_worker(name):
    global pause_event
    for w in workers:
        if w.name == name:
            pause_event.clear()
            print(f"{name} paused")

def resume_worker(name):
    global pause_event
    for w in workers:
        if w.name == name:
            pause_event.set()
            print(f"{name} resumed")

if __name__ == "__main__":
    pause_event = threading.Event()
    pause_event.set()

    t1 = threading.Thread(target=worker, args=("A", pause_event), name="A")
    workers.append(t1)
    t2 = threading.Thread(target=worker, args=("B", pause_event), name="B")
    workers.append(t2)

    t1.start()
    t2.start()

    time.sleep(0.3)
    pause_worker("A")
    time.sleep(0.5)
    resume_worker("A")
    time.sleep(0.3)
    pause_worker("A")
    time.sleep(0.3)
    resume_worker("A")

    t1.join()
    t2.join()

Output

stdout
A step 0
B step 0
A step 1
B step 1
A step 2
B step 2
A step 3
B step 3
A paused
B step 4
B step 5
B step 6
B step 7
A resumed
A step 4
B step 8
A step 5
B step 9
A step 6
A paused
A step 7
A resumed
A step 8
A step 9

How it works

The threading.Event object acts as a simple flag that threads can check with wait(). When the event is set, wait() returns immediately, allowing the worker to proceed; when cleared, wait() blocks the thread until the event is set again. The main thread controls the event by calling clear() to pause and set() to resume, affecting only the target worker because each worker uses its own event instance. The sleep calls in the main thread give a deterministic sequence for demonstration, but in real code you'd use condition variables or queues for more complex coordination.

Common mistakes

  • Using `event.wait()` without a timeout can hang threads if the event is never set again.
  • Modifying a global event from multiple threads without synchronization can cause race conditions.
  • Assuming `clear()` instantly stops a thread mid-iteration; it only blocks at the next `wait()` call.
  • Forgetting to set the event initially before starting threads, causing them to block immediately.

Variations

  1. Use `threading.Condition` to wait for specific conditions and notify specific threads.
  2. Use a `queue.Queue` with sentinel values to control worker shutdown or pausing in a producer-consumer pattern.

Real-world use cases

  • Pausing a background data-sync worker when the network is down and resuming when connectivity returns.
  • Throttling CPU-intensive tasks during peak hours by pausing worker threads until off-peak time.
  • Coordinating multiple threads in a simulation to advance only when the main thread gives a go-ahead signal.

Sponsored

Run this sample

Open the browser IDE to tweak the example and see results without installing anything.

Open editor

More from Concurrency & performance

Related tutorials and quizzes for this topic.