Foundations & Models
Can you explain the conceptual difference between concurrency and parallelism? Can a single-core machine achieve both?
Can you walk through the typical lifecycle and states of a thread, from creation to termination?
Explain the difference between a thread and a process in terms of memory isolation and communication overhead. Why are threads often preferred for high-performance concurrency?
How does introducing concurrency typically affect a system's throughput versus its latency? When might adding more threads actually decrease performance?
What are the primary overhead costs associated with multi-threading?
What is a context switch, and why is it computationally expensive? How do lightweight concurrency models like coroutines mitigate this cost?
What is the difference between Cooperative and Preemptive multitasking?
What is the difference between CPU-bound and I/O-bound tasks, and how does that change your choice of concurrency model?
What is thread oversubscription, and how does having more runnable threads than cores affect performance?
Why does concurrency often lead to non-deterministic behavior in a program?
Concurrency Patterns
Compare the 'Shared Memory' model with the 'Message Passing' (CSP) model. What are the trade-offs?
Describe the producer-consumer problem. Why is a bounded buffer usually preferred over an unbounded one in production systems?
In Go-style concurrency (CSP), why is it said to 'Share memory by communicating, not communicate by sharing memory'?
What are the core principles of the Actor Model? How does it handle state isolation and fault tolerance?
What are the guarded-suspension and balking patterns, and when would you use each?
What is 'structured concurrency'? How does it improve the management of task lifetimes and error propagation compared to 'fire-and-forget' threads?
What is a blocking queue, and why is it a natural fit for the producer-consumer pattern?
What is the 'Producer-Consumer' problem, and what synchronization primitives are typically used to solve it?
Async & Event Driven Io
Conceptually, what is the C10K problem, and how did the shift from 'thread-per-connection' to 'event-driven' architectures solve it?
Explain how a single-threaded event loop can handle thousands of concurrent I/O requests without threads.
Explain the 'Async/Await' model. What happens to the underlying thread when an await point is reached?
How can futures/promises be composed and chained, and how does error propagation work through such a chain?
How is cancellation and timeout handling coordinated in asynchronous or task-based code, and why is cooperative cancellation preferred over forceful termination?
What are the Reactor and Proactor patterns, and how do they differ in handling I/O readiness versus completion?
What happens under the hood when a program encounters an await keyword, and how is the execution state preserved?
What is 'callback hell,' and how do futures/promises or async/await address it?
What is Backpressure, and why is it critical in concurrent data pipelines?
What is the 'GIL' (Global Interpreter Lock) in languages like Python or Ruby, and how does it impact multi-core utilization?
What is the conceptual difference between a Future and a Promise? How do they help manage the 'callback hell' problem?
What is the difference between blocking and non-blocking I/O, and how does non-blocking I/O let a small number of threads serve many connections?
When would you prefer an Asynchronous (Event-Loop) model over a Multithreaded model?
Memory Model & Visibility
Concurrency correctness is often framed around three concerns: atomicity, visibility, and ordering. Can you explain what each one means?
Explain the double-checked locking pattern. Why is the volatile keyword necessary for this pattern to be thread-safe in modern memory models?
In the context of a language memory model, what does the 'happens-before' relationship guarantee? Why is it critical for visibility?
What is a 'Memory Barrier' (or Fence), and what is the difference between Acquire and Release semantics?
What is a memory barrier, and how does it enforce ordering between different threads?
What is a Memory Model (e.g., JMM or C++11 model), and why do we need one?
What is safe publication of an object, and why can sharing a reference across threads without proper synchronization expose a partially constructed object?
What is sequential consistency as a memory model guarantee, and why don't most real systems provide it by default?
What is the difference between marking a variable as volatile versus using an Atomic type? Does volatile guarantee atomicity for increment operations?
What is the difference between Sequential Consistency and Eventual Consistency in a multi-threaded program?
What is the volatile keyword's effect on visibility and instruction reordering?
Why do compilers and CPUs reorder instructions, and how can this break concurrent code that looks correct on paper?
Locks & Synchronization Primitives
Explain the 'Readers-Writers' problem. Why would you use a Read-Write Lock instead of a standard Mutex?
Explain the Condition Variable and why you must always call wait() inside a loop.
Explain the Readers-Writers problem. What are the trade-offs between a 'read-preferring' and a 'write-preferring' implementation?
How would you coordinate a Producer-Consumer relationship using only a Mutex and a Condition Variable? Why must the 'wait' call always be inside a loop?
What is 'Lock Striping' (or Lock Splitting), and how does it improve the scalability of a concurrent data structure?
What is a 'Reentrant Lock' (or Recursive Lock), and what problem does it solve?
What is a barrier (or a CountDownLatch/phaser), and how does it differ from a lock as a synchronization tool?
What is a monitor, and how does it combine mutual exclusion with condition-based waiting?
What is a Spinlock, and in what specific scenario is it more efficient than a blocking Mutex?
What is a spurious wakeup, and how should code handle it?
What is a try-lock (or timed lock), and how can it be used to avoid deadlock?
What is the difference between coarse-grained and fine-grained locking? How does 'lock striping' help improve the scalability of a concurrent data structure?
What is the difference between Optimistic and Pessimistic Locking? When would you prefer one over the other?
What is the fundamental difference between a mutex and a semaphore? In what scenario would you use a counting semaphore instead of a binary mutex?
When would you prefer a ReadWriteLock over a standard reentrant lock, and what is the risk of writer starvation in this model?
Why can Lock Contention lead to poor CPU utilization even when you have many cores?
Lock Free & Atomics
Explain the ABA problem in lock-free data structures, and how do tagged pointers or hazard pointers solve it?
How does the CAS (Compare-and-Swap) operation work? Why is it considered the building block of lock-free programming?
What are the differences between test-and-set, fetch-and-add, and compare-and-swap as atomic primitives?
What is Read-Copy-Update (RCU), and in what read-heavy scenarios is it beneficial?
What is the difference between Lock-free, Wait-free, and Obstruction-free algorithms?
Why are lock-free data structures often more performant under high contention than lock-based ones?
Why can a striped atomic accumulator (like a LongAdder) outperform a single atomic counter under high contention?
Why is designing correct lock-free data structures so difficult compared to using locks?
Why is it generally harder to implement a lock-free Queue than a lock-free Stack?
Shared State & Thread Safety
Explain the Check-Then-Act race condition.
Explain the Copy-On-Write strategy and its benefits/drawbacks in a concurrent environment.
How do you categorize classes by thread-safety, immutable, thread-safe, conditionally thread-safe, and thread-hostile?
How would you approach designing a thread-safe class: what strategies exist for encapsulating and protecting mutable state?
How would you implement thread-safe lazy initialization, and what are the pitfalls?
What are the risks of using ThreadLocal variables in a thread-pooled environment?
What does it mean for a class to be 'Thread-Safe'? Does using thread-safe collections make your entire application thread-safe?
What does it mean for a function to be Reentrant? Is every thread-safe function reentrant?
What is a benign race condition, and how does it differ from a harmful one?
What is the difference between synchronized/wrapper collections and truly concurrent collection implementations?
What is the read-modify-write problem, and why do operations like incrementing a counter require synchronization?
What is the technical distinction between a race condition and a data race, and can you have one without the other?
What is thread confinement, how do ThreadLocal variables help achieve it, and what are the risks of using them in a thread-pooled environment?
Why is immutability such a powerful tool for concurrency, and are there performance trade-offs to using copy-on-write strategies?
Why is shared mutable state the fundamental source of difficulty in concurrent programming, and what design strategies minimize it?
Deadlock Livelock & Contention
Explain the difference between livelock and starvation, and how can a fair locking strategy help prevent starvation?
Explain the Dining Philosophers problem. What does it illustrate about deadlock, and how can it be solved?
How do you detect a deadlock in a running application?
How do you distinguish between Deadlock, Livelock, and Starvation?
How do you identify lock contention in a running application, and what are three strategies to reduce it?
How do you prevent Deadlock in a system that requires acquiring multiple locks?
What are the four Coffman conditions required for a deadlock to occur, and how can you prevent deadlock by breaking one of these conditions?
What is a lock convoy, and what conditions cause one to form?
What is priority inversion, and how can a 'priority inheritance' protocol solve it?
What is the difference between deadlock prevention, avoidance, and detection from a programmer's perspective?
Thread Pools & Lightweight Threads
Explain the work-stealing algorithm. How does it improve resource utilization compared to a simple work-sharing approach?
How does a thread pool work, and what factors should you consider when deciding the optimal number of threads for a pool for CPU-bound vs I/O-bound work?
What are coroutines and continuations, and how do they enable lightweight cooperative concurrency?
What are virtual (or green) threads, and how do they differ from traditional OS/platform threads? Why are they particularly useful for I/O-bound tasks?
What is 'Thread Pinning' in the context of virtual threads, and why is it a performance concern?
What is M:N (many-to-many) threading, where many user-mode threads are multiplexed onto fewer OS threads, and what advantages does it give a runtime?
Why do we use thread pools instead of creating a new thread for every task? What are the risks of a thread pool that is too small versus one that is too large?
Parallelism & Decomposition
How do you decompose a problem for parallel execution, and how does task granularity affect the outcome?
How does the map-reduce pattern express parallelism, and what kinds of problems fit it?
What does it mean for a workload to be 'embarrassingly parallel,' and why do such problems scale so well?
What is pipeline (dataflow) parallelism, and when is it a good decomposition strategy?
What is the difference between task parallelism and data parallelism? Give an example of a workload suited for each.
Performance Scalability & Testing
What is 'false sharing' at the CPU cache level, and how can a programmer structure their data to avoid it?
What is Amdahl's Law, and how does it help you determine the maximum theoretical speedup of a program when adding more CPU cores?
What is Gustafson's Law, and how does it offer a more optimistic view of parallel scalability than Amdahl's Law?
What is the difference between Strong Scaling and Weak Scaling?
Why is it difficult to test concurrent code, and how would you reproduce a heisenbug that only occurs occasionally in production?