POC Concurrency & Multithreading 2 — Questions and Answers
Question 1: Which class in the `concurrent.futures` module is best suited for thread-based parallelism?
- ThreadPoolExecutor (Correct answer)
- ProcessPoolExecutor
- AsyncExecutor
- ConcurrentThreadPool
Correct answer: ThreadPoolExecutor
ThreadPoolExecutor manages a pool of worker threads and provides a high-level interface for submitting tasks and retrieving results via Future objects.
Question 2: What is the primary purpose of a threading.Lock object in Python?
- To permanently block a thread from running
- To synchronize access to shared resources, preventing simultaneous modification by multiple threads (Correct answer)
- To set a maximum limit on the number of threads in a program
- To monitor and log thread execution performance
Correct answer: To synchronize access to shared resources, preventing simultaneous modification by multiple threads
A Lock ensures mutual exclusion — only one thread can acquire the lock at a time, preventing race conditions on shared data.
Question 3: In Python's asyncio framework, which keyword suspends a coroutine until an awaitable completes?
- pause
- suspend
- await (Correct answer)
- yield
Correct answer: await
The `await` keyword suspends the current coroutine and yields control back to the event loop, which resumes it when the awaitable is done.
Question 4: What is a deadlock in a multithreaded Python program?
- A condition where a thread runs an infinite loop consuming all CPU
- A situation where two or more threads wait indefinitely for locks held by each other (Correct answer)
- A crash caused by creating more threads than the system supports
- A performance degradation from excessive thread context switching
Correct answer: A situation where two or more threads wait indefinitely for locks held by each other
Deadlock occurs when Thread A holds Lock 1 and waits for Lock 2, while Thread B holds Lock 2 and waits for Lock 1 — both block forever.
Question 5: Which method of threading.Thread should you override in a subclass to define the thread's work?
- execute()
- start()
- run() (Correct answer)
- begin()
Correct answer: run()
Overriding run() defines the code executed in the new thread; start() internally calls run() in a new thread context.
Question 6: What is the primary advantage of asyncio over threading for I/O-bound tasks in Python?
- asyncio utilizes multiple CPU cores simultaneously for faster computation
- asyncio bypasses the GIL, allowing true parallelism
- asyncio uses cooperative multitasking, eliminating thread-switching overhead and scaling to thousands of concurrent tasks (Correct answer)
- asyncio is faster than threading for CPU-intensive operations
Correct answer: asyncio uses cooperative multitasking, eliminating thread-switching overhead and scaling to thousands of concurrent tasks
asyncio's event loop runs in a single thread using cooperative multitasking — coroutines yield control voluntarily, avoiding the overhead of OS thread switching.
Question 7: Which module and class should be used to safely pass data between threads using a FIFO queue?
- threading.Queue
- queue.Queue (Correct answer)
- concurrent.Queue
- collections.deque
Correct answer: queue.Queue
queue.Queue is thread-safe by design, using internal locks to prevent race conditions when multiple threads produce and consume items.
Which class in the `concurrent.futures` module is best suited for thread-based parallelism?