Your country

Tools that support it use your country for local currency, number formats, units and paper size. Your choice is saved only in this browser.

Type a name or a two-letter code. Use the up and down arrow keys to move through the countries, Enter to choose one and Escape to close.

Coding Interview Patterns Module 31

Concurrency coding problems interview questions

Interview questions on concurrency coding problems: short warm-ups, then what each harder question tests, the first step of a good answer and its follow-ups.

12 questions: 3 warm-ups and 9 with model answers · Levels: Fresher to staff

Warm-up questions

Short questions with short answers, each answered in full.

  1. Fresher to mid

    How does a concurrency limit differ from a rate limit, and when do you need both?

    Answered in the lesson Running tasks with a concurrency limit

  2. Fresher to mid

    What does put do on a full bounded queue, and why is that behaviour useful?

    It waits. A blocking put on a full bounded queue returns only once a consumer has taken an item and made room, so the producer runs no faster than the consumers drain the queue. That is backpressure, and it is the reason to bound the queue: memory stays at the queue's size however fast the producers are, and the slowdown travels back to whoever makes the work, which can then shed load or ask its own callers to slow down. Most queues also offer a put that does not wait: Python's put_nowait raises Full, Java's offer returns false, and a put with a time limit gives up when it runs out. Those suit work that may be dropped or retried, such as metrics; a blocking put suits work that must not be lost.

    From the lesson Bounded buffers and ordered workers

  3. Fresher to mid

    When is an atomic counter enough, and when do you need a lock?

    An atomic is enough when the shared state is one variable and every update is one operation on it: add one, swap, or compare-and-set. Java's AtomicLong, Go's atomic.Int64 and C++'s std::atomic do the read, the change and the write as one indivisible step, so no update is lost and no lock is needed. You need a lock when two or more values must change together, or when a decision depends on what you read: a balance and its list of transactions, the map and the list of an LRU cache, or "take a seat only if one is free". Two atomic variables updated one after the other can still be seen half updated by another thread. A compare-and-set loop stretches an atomic a little further, but once the rule involves more than one value, a lock is clearer.

    From the lesson Thread-safe counters, caches and aggregation

Questions with model answers

What each question tests, the first step of a good answer and the follow-ups to expect.

  1. Mid to senior

    A nightly job looks up 50,000 orders in a partner's API, which allows 20 requests in flight and answers in about 400 ms. How long will the job take, how do you write the loop, and what do you do when some calls fail?

    What it tests
    Sizing with Little's law, a bounded pool of workers instead of unbounded tasks, and a failure policy with retries that keeps the job resumable.
    First step
    Work out the ceiling before writing code. Twenty requests in flight at 400 ms each allow at most 20 ÷ 0.4 = 50 calls a second, so 50,000 calls need at least 1,000 seconds, about 17 minutes. Then keep exactly 20 calls busy: 20 workers that take the next order from a shared index or a queue, never 50,000 tasks created at once.
    Follow-ups

    From the lesson Running tasks with a concurrency limit

    Model answer, Pro. Model answers open with any pass; prices are in the notice on this page.

    Opening the model answers with your pass…

    Model answers open with any MySmartCoPilot pass.

    • Pro pass · 1 week₹79$2.99
    • 30 days₹179$5.99
    • 1 year₹1,699$45

    One payment; a pass never renews. The price shown is the total you pay: no fees or charges are added at checkout.

    It also opens every other in-depth part in Learn and every Pro tool. Sales are final, except where the law gives you a right to withdraw, for example in the EU and the UK (refund policy).

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 5 minutes
  2. Fresher to mid

    A web page uploads 10,000 photos with Promise.all(photos.map(upload)). Users report frozen tabs and failed uploads. Rewrite it so that at most 6 uploads run at once, the results keep their order, and one failed photo does not lose the others.

    What it tests
    Seeing that map starts every promise at once, writing a promise pool with a shared index, and choosing a failure policy and honest progress for a user.
    First step
    Promise.all limits nothing: map calls upload for every photo before the first await, so all 10,000 requests start together. Replace it with 6 async workers that loop: take the next index with no await in between, await upload(photos[i]) and store the outcome at index i. Then decide what a failure means for the user; usually every photo is settled and the failed ones are offered for a retry.
    Follow-ups

    From the lesson Running tasks with a concurrency limit

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 3 minutes
  3. Senior to staff

    A crawler runs 8 workers that take URLs from a shared queue, and every page they fetch can add new links to it. How do you know when the crawl has finished, and how do you keep its memory bounded?

    What it tests
    Detecting the end when tasks create tasks, counting pending work instead of watching for an empty queue, deduplication, and a bounded frontier.
    First step
    An empty queue does not mean the crawl is over: a worker that is still fetching a page may add links a moment later. Count pending work instead: add one when a URL is queued, and subtract one when its page has been fully processed, after its links are queued. The crawl ends when the count reaches zero, and only then are the workers told to stop.
    Follow-ups

    From the lesson Running tasks with a concurrency limit

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 4 minutes
  4. Mid to senior

    A service hands log lines to a background thread through an unbounded queue. When the log server goes down for 10 minutes, memory grows until the service is killed. Redesign the hand-off, and say what happens to log lines while the log server is down.

    What it tests
    Seeing that an unbounded queue turns an outage into memory growth, sizing a bound with numbers, and choosing between blocking, dropping and spilling to disk.
    First step
    Put numbers on the growth first. At 5,000 lines a second and about 200 bytes a line, a 10-minute outage queues 3 million lines, about 600 MB before any object overhead. The fix is a bound, and then a decision about what happens at the bound: block the request threads, drop lines, or spill them to disk.
    Follow-ups

    From the lesson Bounded buffers and ordered workers

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 4 minutes
  5. Mid to senior

    A pipeline reads files on 1 thread, parses them on 4 threads and writes rows to a database on 2 threads, with bounded queues between the stages. How do you stop it cleanly when the input ends, and what happens when one parser fails halfway?

    What it tests
    The order of shutdown across stages, counting producers before closing a queue, and stopping every stage on a failure without deadlocks on full or empty queues.
    First step
    Stop it from the front. When the reader runs out of files, it closes the first queue, or puts one sentinel per parser into it. The second queue may close only after all 4 parsers have finished, so the last parser to finish closes it, found with a count of finished parsers. The writers stop once the second queue is closed and empty, and then the pipeline is done.
    Follow-ups

    From the lesson Bounded buffers and ordered workers

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 4 minutes
  6. Fresher to mid

    A start-up script launches three threads at once: one opens the database connection, one warms the cache, one starts serving requests. Warming needs the connection, and serving needs the warm cache. Make the order hold however the threads are scheduled, then extend it to n steps where some steps may run in parallel.

    What it tests
    Hand-offs with semaphores, latches or futures, and generalising them to a graph of dependencies whose independent steps run in parallel.
    First step
    Give each hand-off its own signal that starts closed: a semaphore at 0, a CountDownLatch of 1, or a future. Warming waits for the connection's signal before it starts, serving waits for the cache's, and each step opens its own signal when it is done. Starting the threads in any order then cannot change the order of the steps.
    Follow-ups

    From the lesson Bounded buffers and ordered workers

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 4 minutes
  7. Mid to senior

    An LRU cache behind one mutex serves 16 threads. Profiles show threads waiting on that mutex at 200,000 calls a second. What do you change, and what do you give up?

    What it tests
    Knowing why a read-write lock does not help an LRU cache, sharding and its effect on eviction, and measuring how long the lock is held before changing the design.
    First step
    Measure first: how long is the lock held per call, and how long do threads wait for it? At 200,000 calls a second, a lock held for 2 µs per call is busy 40 % of the time, and waits climb steeply as that share rises. Then shorten the critical section before splitting it: nothing slow, such as a load from the database, may run under the lock.
    Follow-ups

    From the lesson Thread-safe counters, caches and aggregation

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 4 minutes
  8. Mid to senior

    A popular product's cache entry expires, and within the next 300 ms, 50 threads miss it and each queries the database, which takes 300 ms per query. How do you make sure only one query runs, without holding the cache's lock during the query?

    What it tests
    Loading once per key with a map of loads in flight, handing the result over safely, handling failures and timeouts, and alternatives such as refreshing before expiry.
    First step
    Keep a second map, of loads in flight, under the cache's lock. The first thread that misses records a placeholder, a future or a channel, releases the lock and runs the query; the next 49 find the placeholder and wait on it. When the query returns, the loader stores the value, removes the placeholder and completes it, so every waiter wakes with the same result.
    Follow-ups

    From the lesson Thread-safe counters, caches and aggregation

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 4 minutes
  9. Mid to senior

    You split a word count over 64 files across 8 threads that all update one ConcurrentHashMap, and it runs slower than one thread did. Why, and how do you make it fast and still exact?

    What it tests
    Contention on shared hot keys and cache lines, private partial results with a merge, and keeping the merge deterministic.
    First step
    Look at where the threads meet. Every word is an update to one shared map, and a few common words take a large share of the updates, so 8 threads queue on the same entries and pass the same cache lines between cores. Give each thread a map of its own and merge the 8 maps at the end: the threads share nothing while they count.
    Follow-ups

    From the lesson Thread-safe counters, caches and aggregation

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 3 minutes

All Coding Interview Patterns interview questions · The Coding Interview Patterns track

Quick answers and tool search

Type to search tools or to get a quick answer, for example 18% of 2500. Use the up and down arrow keys to move through the results, Enter to choose, and Escape to close.