Foundations & Models
Can you explain the conceptual difference between concurrency and parallelism? Can a single-core machine achieve both?
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?
Why does concurrency often lead to non-deterministic behavior in a program?
What is the difference between CPU-bound and I/O-bound tasks, and how does that change your choice of concurrency model?
Can you walk through the typical lifecycle and states of a thread, from creation to termination?
What is the difference between Cooperative and Preemptive multitasking?
What is a context switch, and why is it computationally expensive? How do lightweight concurrency models like coroutines mitigate this cost?
What are the primary overhead costs associated with multi-threading?
What is thread oversubscription, and how does having more runnable threads than cores affect performance?
How does introducing concurrency typically affect a system's throughput versus its latency? When might adding more threads actually decrease performance?
Shared State & Thread Safety
Explain the Check-Then-Act race condition.
Why is shared mutable state the fundamental source of difficulty in concurrent programming, and what design strategies minimize it?
What is the read-modify-write problem, and why do operations like incrementing a counter require synchronization?
What is thread confinement, how do ThreadLocal variables help achieve it, and what are the risks of using them 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?
Why is immutability such a powerful tool for concurrency, and are there performance trade-offs to using copy-on-write strategies?
How would you implement thread-safe lazy initialization, and what are the pitfalls?
What is the difference between synchronized/wrapper collections and truly concurrent collection implementations?
What is the technical distinction between a race condition and a data race, and can you have one without the other?
What does it mean for a function to be Reentrant? Is every thread-safe function reentrant?
Explain the Copy-On-Write strategy and its benefits/drawbacks in a concurrent environment.
What are the risks of using ThreadLocal variables in a thread-pooled environment?
How do you categorize classes by thread-safety, immutable, thread-safe, conditionally thread-safe, and thread-hostile?
What is a benign race condition, and how does it differ from a harmful one?
How would you approach designing a thread-safe class: what strategies exist for encapsulating and protecting mutable state?
Locks & Synchronization Primitives
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?
What is the difference between Optimistic and Pessimistic Locking? When would you prefer one over the other?
Explain the Condition Variable and why you must always call wait() inside a loop.
What is a 'Reentrant Lock' (or Recursive Lock), and what problem does it solve?
When would you prefer a ReadWriteLock over a standard reentrant lock, and what is the risk of writer starvation in this model?
Explain the 'Readers-Writers' problem. Why would you use a Read-Write Lock instead of a standard Mutex?
What is a Spinlock, and in what specific scenario is it more efficient than a blocking Mutex?
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 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 try-lock (or timed lock), and how can it be used to avoid deadlock?
What is a spurious wakeup, and how should code handle it?
What is 'Lock Striping' (or Lock Splitting), and how does it improve the scalability of a concurrent data structure?
What is the difference between coarse-grained and fine-grained locking? How does 'lock striping' help improve the scalability of a concurrent data structure?
Why can Lock Contention lead to poor CPU utilization even when you have many cores?
Explain the Readers-Writers problem. What are the trade-offs between a 'read-preferring' and a 'write-preferring' implementation?
Deadlock Livelock & Contention
What are the four Coffman conditions required for a deadlock to occur, and how can you prevent deadlock by breaking one of these conditions?
How do you distinguish between Deadlock, Livelock, and Starvation?
How do you prevent Deadlock in a system that requires acquiring multiple locks?
Explain the difference between livelock and starvation, and how can a fair locking strategy help prevent starvation?
How do you detect a deadlock in a running application?
Explain the Dining Philosophers problem. What does it illustrate about deadlock, and how can it be solved?
What is priority inversion, and how can a 'priority inheritance' protocol solve it?
How do you identify lock contention in a running application, and what are three strategies to reduce it?
What is a lock convoy, and what conditions cause one to form?
What is the difference between deadlock prevention, avoidance, and detection from a programmer's perspective?
Memory Model & Visibility
What is the volatile keyword's effect on visibility and instruction reordering?
What is the difference between marking a variable as volatile versus using an Atomic type? Does volatile guarantee atomicity for increment operations?
Concurrency correctness is often framed around three concerns: atomicity, visibility, and ordering. Can you explain what each one means?
In the context of a language memory model, what does the 'happens-before' relationship guarantee? Why is it critical for visibility?
Explain the double-checked locking pattern. Why is the volatile keyword necessary for this pattern to be thread-safe in modern memory models?
Why do compilers and CPUs reorder instructions, and how can this break concurrent code that looks correct on paper?
What is a Memory Model (e.g., JMM or C++11 model), and why do we need one?
What is the difference between Sequential Consistency and Eventual Consistency in a multi-threaded program?
What is a memory barrier, and how does it enforce ordering between different threads?
What is a 'Memory Barrier' (or Fence), and what is the difference between Acquire and Release semantics?
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?
Lock Free & Atomics
How does the CAS (Compare-and-Swap) operation work? Why is it considered the building block of lock-free programming?
Explain the ABA problem in lock-free data structures, and how do tagged pointers or hazard pointers solve it?
What is the difference between Lock-free, Wait-free, and Obstruction-free algorithms?
Why is it generally harder to implement a lock-free Queue than a lock-free Stack?
Why are lock-free data structures often more performant under high contention than lock-based ones?
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?
Why is designing correct lock-free data structures so difficult compared to using locks?
Why can a striped atomic accumulator (like a LongAdder) outperform a single atomic counter under high contention?
Async & Event Driven Io
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?
Explain how a single-threaded event loop can handle thousands of concurrent I/O requests without threads.
What is the conceptual difference between a Future and a Promise? How do they help manage the 'callback hell' problem?
When would you prefer an Asynchronous (Event-Loop) model over a Multithreaded model?
Explain the 'Async/Await' model. What happens to the underlying thread when an await point is reached?
What is the 'GIL' (Global Interpreter Lock) in languages like Python or Ruby, and how does it impact multi-core utilization?
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?
How can futures/promises be composed and chained, and how does error propagation work through such a chain?
Conceptually, what is the C10K problem, and how did the shift from 'thread-per-connection' to 'event-driven' architectures solve it?
What happens under the hood when a program encounters an await keyword, and how is the execution state preserved?
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?
Thread Pools & Lightweight Threads
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?
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?
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?
Explain the work-stealing algorithm. How does it improve resource utilization compared to a simple work-sharing approach?
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?
Concurrency Patterns
What is the 'Producer-Consumer' problem, and what synchronization primitives are typically used to solve it?
What is a blocking queue, and why is it a natural fit for the producer-consumer pattern?
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 is 'structured concurrency'? How does it improve the management of task lifetimes and error propagation compared to 'fire-and-forget' threads?
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?
Parallelism & Decomposition
What does it mean for a workload to be 'embarrassingly parallel,' and why do such problems scale so well?
What is the difference between task parallelism and data parallelism? Give an example of a workload suited for each.
What is pipeline (dataflow) parallelism, and when is it a good decomposition strategy?
How does the map-reduce pattern express parallelism, and what kinds of problems fit it?
How do you decompose a problem for parallel execution, and how does task granularity affect the outcome?
Performance Scalability & Testing
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 'false sharing' at the CPU cache level, and how can a programmer structure their data to avoid it?
Why is it difficult to test concurrent code, and how would you reproduce a heisenbug that only occurs occasionally in production?
What is the difference between Strong Scaling and Weak Scaling?
What is Gustafson's Law, and how does it offer a more optimistic view of parallel scalability than Amdahl's Law?