Skip to content
Preptima

Top 26 Concurrency Interview Questions

Browse 26 real-world technical and behavioral interview questions about Concurrency. Review scenarios, edge cases, and architectural best practices.

Build an in-memory pub-sub with topics, many subscribers per topic and at-least-once delivery. How does a message get redelivered?

An in-memory pub-sub with at-least-once delivery stores each topic as an append-only log and gives every subscriber its own cursor and in-flight set. A message stays in flight until acknowledged and is redelivered after an ack timeout, so a slow subscriber only delays itself and every handler must tolerate duplicates.

hardcoding

Design an in-memory job scheduler that runs one-off, delayed and recurring jobs. Write the core classes.

An in-memory job scheduler keeps one queue ordered by next run time, such as a DelayQueue, and one dispatcher thread that hands due entries to a worker pool. Recurring jobs are re-queued after each run, cancellation is a generation check on dequeue, and missed runs need a stated skip or catch-up policy.

hardcoding

A flash sale decrements stock from many threads. Do you go optimistic or pessimistic, and how do you prove nothing oversold?

For one stock counter, optimistic locking with a compare-and-set loop fits: read, refuse at zero, and publish the decrement only if nobody changed the value meanwhile. A lock suits a larger critical section. Prove it by arguing each sale consumes one unit, plus a stress test seen to fail on the broken code.

mediumcoding

State the four conditions for deadlock, then show me how you would stop a real program from deadlocking.

Deadlock needs all four Coffman conditions at once: mutual exclusion, hold and wait, no preemption and circular wait. Breaking any one prevents it, and the practical choice is usually circular wait, by making every thread take locks in one global order.

easyconcept

Implement a thread-safe pool of N connections with acquire, release and a timeout.

A thread-safe connection pool pairs a Semaphore of N permits, which bounds how many connections exist and gives acquire its timeout, with a queue of idle connections. Acquire returns a lease that releases exactly once from a finally block, and a broken connection is discarded without losing its permit.

hardcoding

Design a movie ticket booking system with shows, seats and a temporary hold that expires if the user does not pay. Write the classes.

A ticket booking design models a Show that owns its seat states and a Hold with an owner, seat set and expiry. Holds are taken all-or-nothing under a per-show lock, expiry is checked lazily so no timer decides correctness, and starting payment moves the hold to a state the timer can no longer release.

hardcoding

One global lock makes your reservation system correct and slow. How do you split it without deadlocking?

Shrink the critical section first, then replace the global lock with lock striping, a fixed array of locks keyed by resource hash. Lock ordering by ascending stripe index rules out deadlock for multi-resource bookings, tryLock bounds waiting, and invariants the old lock covered by accident each need an owner.

harddesign

Two users click "book" on the last seat in your in-memory booking class at the same moment. Where does the lock go?

The bug is a check-then-act race condition: both threads see the seat free before either marks it taken. The lock must cover the check and the write together, scoped to one show so unrelated shows never wait, and released before payment, with a timed hold standing in for the seat while the user pays.

mediumcoding

Two processes share a memory region and both write to it. What do you need besides the memory, and what happens if one of them dies while holding the lock?

Shared memory gives you bytes, not coordination. Process synchronisation needs a mutex inside the region, marked PTHREAD_PROCESS_SHARED and initialised once. If the holder dies, a plain mutex stays locked forever; a robust mutex returns EOWNERDEAD, but repairing half-written data is your job.

hardconcept

An asyncio call times out and you handle the TimeoutError, but the background task keeps running and mutates shared state a few seconds later. What happened, and how do you make the timeout actually stop the work?

A timeout requests cancellation; it does not stop code. CancelledError is raised at the task next await point, so a task inside blocking code, shielded, in an executor thread, or swallowing the exception keeps running and commits its side effects late. Fix by re-raising CancelledError, keeping blocking calls off the loop, and using asyncio.timeout with a TaskGroup.

hardconcept

Design a rate limiter that allows N requests per client per minute. Write the class.

A rate limiter machine coding solution should reject fixed-window boundary bursts, usually with a token bucket. It needs no per-request history and stores two numbers per client, but only if refill is computed lazily from a timestamp rather than by running a background thread. Use this rate limiting answer to show the decision, trade-off, and evidence rather than a memorised definition.

mediumcoding

How would you design a thread-safe component, and why is adding synchronized to every method not a design?

Thread-safe component design starts by assigning every field a policy: confined, immutable or guarded by a named lock. Method-level synchronization is not enough because atomic methods do not compose into atomic workflows.

hardconcept

Design a distributed lock manager for a high-frequency trading platform where microsecond latency is critical and stale locks can result in massive financial losses.

Designing an ultra-low latency distributed lock manager, evaluating consensus algorithms, and handling clock drift in high-frequency environments.

hardscenario

A family plan shares 100 GB across five SIMs with each SIM capped at 30 GB. How does charging enforce both limits at once?

Every reservation must decrement the shared pool and the member's own counter atomically, granting the smallest of the two remainders. That makes the group rather than the subscriber the serialisation point, and it means a member with headroom can still be refused because the pool is gone.

harddesign

Two threads write to adjacent counters and throughput collapses. What is happening and how do you fix it?

They are false sharing: both counters sit in one cache line, so each write invalidates the other core's copy and the line ping-pongs between caches. You fix it by aligning each hot field to its own line, at the cost of footprint, and only where a hardware counter says so. It also connects cache lines to the point an interviewer is testing.

hardconcept

A rider requests a car and forty drivers are within range. Which one do you pick, and how long do you have to decide?

Ride matching system design should rank drivers by estimated pickup time and market impact, not straight-line distance. Offer the ride under a short soft lock, use a small batching window when it improves assignment quality, and keep the rider wait within a few seconds. Use this dispatch answer to show the decision, trade-off, and evidence rather than a memorised definition.

hardcase study

What does the GIL actually prevent, and how do you decide between threads, processes, and asyncio?

The Python GIL serializes CPython bytecode execution, but threads still help I/O-bound work; choose processes for pure Python CPU work and asyncio for many concurrent waits.

mediumconcept

Every call you make is on a ConcurrentHashMap, and you still lost an update. How does a thread-safe collection get raced?

Thread safety composes per operation, not across operations. A get followed by a put is two atomic steps with a legal interleaving between them. You close the window by making the whole compound action one operation, such as compute or merge, or by holding a single lock across both steps.

hardconcept

Design a producer-consumer pipeline with a bounded buffer. What do you do when the buffer is full?

A producer-consumer bounded buffer applies backpressure to the producer instead of letting an unbounded queue absorb overload until the process dies. Deciding what a full buffer does - block, drop, or reject - is the decision that determines how the system fails.

harddesign

Two customers try to buy the last item at the same time. How do you handle inventory?

Treat availability as a claim you grant, not a number you read: fold the check and the decrement into one conditional write, hold the winner's claim as a reservation that expires, and choose deliberately how much overselling you accept, because the warehouse and not the database is the real source of truth.

harddesign

An operation in this code takes two locks and it deadlocks every few weeks. How would you design the locking so that cannot happen?

A deadlock is a cycle in the wait-for graph, so the design goal is a graph that cannot contain one: stop holding two locks where you can, impose one total order on acquisition everywhere you cannot, and never call unknown code while holding a lock.

harddesign

Two users edit the same record and both save. What does EF Core do about it?

EF Core optimistic concurrency uses a rowversion or concurrency token so a stale update affects zero rows instead of overwriting another user's change. The application must then merge, retry or ask the user.

mediumconcept

What belongs inside an interrupt service routine, and what must be kept out of it?

Interrupt service routine rules are simple: acknowledge the hardware, capture the minimum safe state and return fast. Blocking calls, allocation, logging and long loops belong in deferred work because ISR runtime becomes worst-case latency for interrupts at the same or lower priority.

mediumconcept

What actually happens during a context switch, and why should an application developer care?

A context switch in an operating system saves one thread's CPU state, runs the scheduler and restores another thread. Application developers care because excessive switches add latency through cache and TLB disruption, lock contention and oversized thread pools. It also connects scheduling to the point an interviewer is testing.

mediumconcept

What problem do virtual threads actually solve, and when do they not help?

Virtual threads make blocking cheap by unmounting from their carrier OS thread whenever they block, so thread-per-request scales to hundreds of thousands of concurrent tasks. Finalised in JDK 21, they do nothing for CPU-bound work, and pooling them defeats their purpose.

mediumconcept

Several producers write to one channel and one consumer reads it. Who closes the channel?

In Go, the sender closes a channel when no more values will be sent; receivers do not close it just because they are done. Multiple senders need coordination so close happens exactly once after all sends finish. Use this channels answer to show the decision, trade-off, and evidence rather than a memorised definition. It also connects goroutines to the point an interviewer is testing.

mediumconcept