Concurrency
Thread-Safe Queues
The queue module for thread-safe inter-thread communication — Queue, LifoQueue, PriorityQueue for producer-consumer patterns.
Interview: Producer-consumer pattern is a classic interview problem — queues are the standard solution.
Python's queue module provides thread-safe FIFO, LIFO, and priority queues for communication between threads. They're the standard way to pass data between producer and consumer threads without explicit locking — all operations are internally synchronized.
Queue Types
Queue(maxsize=0)— FIFO queue (first in, first out). maxsize=0 means infiniteLifoQueue(maxsize)— LIFO/stack (last in, first out)PriorityQueue(maxsize)— items retrieved in priority order (lowest first)SimpleQueue()— unbounded FIFO without task tracking (simpler, faster)
Key Methods
put(item, block=True, timeout=None)— add item (blocks if full)get(block=True, timeout=None)— remove and return item (blocks if empty)task_done()— signal that a dequeued task is completejoin()— block until all items have been processed (all task_done called)qsize(),empty(),full()— status checks (may be unreliable with threads)
Producer-Consumer Pattern
- Producers call
put()to add work items - Consumers call
get()in a loop, process items, then calltask_done() - Main thread calls
join()to wait for all work to complete - Use a sentinel value (like
None) to signal consumers to stop
Interview Insight
Queues are the standard solution for the producer-consumer pattern. The key insight: queues handle synchronization internally — no locks needed. Use task_done() + join() to know when all work is complete. Bounded queues (maxsize > 0) provide natural back-pressure.
Common Pitfall
Don't call qsize() for flow control — it may return stale values in multi-threaded code. Use empty() and full() with timeouts, or better yet, use blocking get()/put() which handle synchronization correctly.
Use Cases
Producer-consumer — decoupling data generation from processing
Worker pools — fixed number of workers processing shared work
Task scheduling — PriorityQueue for priority-based execution
Rate limiting — bounded queues provide natural back-pressure
Pipeline stages — queues connecting processing stages
Common Mistakes
Not calling task_done() — join() will block forever waiting for completion
Forgetting to stop consumers — without sentinels, consumer threads run forever
Using qsize() for flow control — unreliable in multi-threaded context
Unbounded queues with fast producers — memory grows without limit; use maxsize
Not joining consumer threads — main program exits before workers finish