Skip to content
tezvyn:

Top 30 Concurrency Interview Questions and Answers

30 multiple-choice questions on Concurrency, drawn from 30 bites out of the 183 tagged Concurrency on Tezvyn. Answer them here or read straight down. Every question carries the correct option, why it is correct, and a link to the bite it came from.

30 questions. Pick an answer, or open “Show the answer” to read it.

Answers are graded in your browser. Nothing is saved, and no XP or streak is earned here. The app keeps score.

  1. Question 1 of 30

    When evaluating a new cloud infrastructure project, which statement accurately reflects the trade-off between using Rust versus Go?

    Show the answer

    Answer: a · Rust provides deterministic latency and compile-time data-race safety at the cost of a steeper learning curve, whereas Go trades runtime GC overhead for simplicity and faster onboarding.

    B is correct because it accurately pairs Rust's deterministic, zero-cost memory safety and compile-time data-race prevention with its steeper learning curve, while recognizing Go's GC introduces runtime overhead in exchange for simplicity and faster onboarding. C is a tempting distractor because Go does automate memory reclamation, but its GC does not prevent data races—memory safety and concurrency safety are distinct, and Go leaves more thread-safety responsibility to the developer.

    Read the full bite: Compare Go's GC and Rust's ownership across performance, productivity, and safety

  2. Question 2 of 30

    Which statement best describes how Node.js handles I/O for thousands of concurrent connections?

    Show the answer

    Answer: a · Network sockets are watched by the OS, while blocking tasks like DNS and file reads use a small internal thread pool.

    Node.js relies on the OS kernel to monitor network sockets and notify the event loop when data arrives, while delegating blocking operations like DNS and some file system work to a limited internal thread pool. Distractor D is tempting because Node is famous for non-blocking I/O, but it wrongly assumes every I/O operation can run without thread assistance.

    Read the full bite: How does Node.js handle thousands of connections on one thread?

  3. Question 3 of 30

    You write an async def FastAPI endpoint that calls requests.get. What is the main risk?

    Show the answer

    Answer: c · The event loop is blocked, freezing concurrent request handling until the call finishes.

    The correct answer is C because calling a blocking library like requests inside async def stalls the event loop, stopping all other requests. The most tempting distractor is A because beginners often assume FastAPI magically threadpools any blocking code, but only def endpoints are run in a threadpool.

    Read the full bite: What is the difference between def and async def in Python and FastAPI?

  4. Question 4 of 30

    In which event loop phase do the majority of completed I/O callbacks, such as a finished network read, actually execute?

    Show the answer

    Answer: d · The poll phase, which retrieves and runs I/O completions

    The poll phase retrieves new I/O events and executes most of their callbacks. The timers phase only handles elapsed setTimeout/setInterval, not I/O completion.

    Read the full bite: Order of the Node.js event loop phases

  5. Question 5 of 30

    A Go server spawns a goroutine per incoming request, and one handler blocks forever reading from a channel that nothing will ever write to. What happens to that goroutine?

    Show the answer

    Answer: b · It stays alive indefinitely, quietly consuming its stack memory, because Go never force-cancels a blocked goroutine on its own

    Go has no automatic timeout or forced cancellation for a blocked goroutine, so it simply stays parked, leaking its stack, until the process exits or something explicitly unblocks it. The runtime does not kill it after a timeout, a single blocked goroutine does not crash the whole program since Go only reports a deadlock when every goroutine is blocked at once, and the garbage collector does not collect a goroutine that could still be unblocked.

    Read the full bite: Goroutines

  6. Question 6 of 30

    Why does wrapping a heavy synchronous computation in an async function fail to keep a Node server responsive?

    Show the answer

    Answer: a · The computation is still synchronous and never yields the single JS thread

    async/await only helps when there is an awaited asynchronous boundary; a synchronous CPU loop still occupies the single thread, blocking the event loop. Worker Threads provide real parallelism.

    Read the full bite: Offloading CPU-bound work with Worker Threads

  7. Question 7 of 30

    What is the primary consequence of running a long-running synchronous task in a Node.js application?

    Show the answer

    Answer: a · The application's event loop will become blocked, making the server unresponsive.

    The card states that a long-running synchronous computation will 'monopolize the single main thread, blocking the event loop entirely,' leading to an unresponsive application. Synchronous tasks are not automatically offloaded to background threads; they execute directly on the main thread, unlike asynchronous I/O operations.

    Read the full bite: The Node.js Event Loop: Concurrency on a Single Thread

  8. Question 8 of 30

    Which implementation correctly minimizes total latency when a FastAPI endpoint must fetch data from two independent external APIs?

    Show the answer

    Answer: a · Inside an async def endpoint, pass two httpx.AsyncClient coroutines to asyncio.gather and await the result.

    asyncio.gather with an async HTTP client schedules both I/O-bound coroutines concurrently on the event loop, reducing total latency to roughly the slower call. Option C is tempting because it uses async/await correctly, but sequential awaiting means the second request cannot start until the first finishes, so latencies add up.

    Read the full bite: How do you structure concurrent API calls with asyncio.gather in FastAPI?

  9. Question 9 of 30

    When a FastAPI endpoint awaiting asyncpg is suspended during a database query, how can Uvicorn process another incoming connection in the same worker process?

    Show the answer

    Answer: d · The event loop yields the coroutine at the await, registers the socket with epoll or kqueue, and schedules the new connection's coroutine on the same thread.

    The correct answer describes cooperative multitasking: the event loop suspends the coroutine at await and interleaves I/O-bound tasks on a single thread. Distractor A is wrong because Uvicorn does not use multiple Python threads to handle requests; concurrency comes from the loop scheduling coroutines, not from threading or GIL behavior.

    Read the full bite: How does Uvicorn use asyncio to handle thousands of concurrent connections?

  10. Question 10 of 30

    What is the immediate result of calling a function defined with async def, like my_coro(), without awaiting it?

    Show the answer

    Answer: c · A coroutine object is returned, which must be explicitly run by an event loop.

    Calling an async def function directly only creates a coroutine object; it does not execute the function's code. This object must then be awaited or scheduled with an event loop to run. Option B describes synchronous function behavior, and Option A incorrectly implies immediate background execution without the necessary explicit step.

    Read the full bite: Python Coroutines: Functions You Can Pause and Resume

  11. Question 11 of 30

    A transaction reads a row twice and gets different committed values each time. Which isolation level permits this while still forbidding dirty reads?

    Show the answer

    Answer: d · Read Committed

    Read Committed forbids dirty reads but allows non-repeatable reads, so committed changes can appear between two reads. Read Uncommitted would also allow dirty reads, which is stricter than the scenario describes.

    Read the full bite: Read Committed versus Serializable isolation levels

  12. Question 12 of 30

    For which scenario would Python's async/await typically NOT provide a performance benefit?

    Show the answer

    Answer: b · Processing a large dataset with intensive numerical calculations.

    Async/await is designed for I/O-bound tasks where the program spends time waiting, allowing other tasks to run during these waits. CPU-bound tasks, like intensive numerical calculations, will block the single event loop, preventing any other tasks from progressing and thus negating the benefits of concurrency.

    Read the full bite: Python's async/await: Concurrent, Not Parallel

  13. Question 13 of 30

    What is the fundamental behavior of the "await" keyword within an "async" function in Swift?

    Show the answer

    Answer: d · It suspends the current task, allowing the system to use the thread for other pending work.

    The "await" keyword suspends the current task, returning the thread to the system to perform other work until the awaited operation completes. It does not block the thread, which is a common misconception.

    Read the full bite: async/await: Write Concurrent Code That Reads Synchronously

  14. Question 14 of 30

    What is the primary advantage of using asynchronous child processes in Node.js?

    Show the answer

    Answer: d · To execute CPU-bound tasks without blocking the main event loop.

    The card explicitly states that child processes solve the problem of CPU-intensive operations blocking the single-threaded event loop by offloading heavy work. Option B describes the purpose of worker_threads, not child processes.

    Read the full bite: Node.js Child Processes: Escaping the Main Thread

  15. Question 15 of 30

    When running a background task that might fail, how do you defer exception handling until the result is actually needed?

    Show the answer

    Answer: d · Use `async` and wrap the call to `await()` in a `try-catch` block.

    `async` encapsulates any exception, which is re-thrown only when `await()` is called, allowing for deferred handling. In contrast, `launch` propagates exceptions immediately, so a `CoroutineExceptionHandler` would trigger right away.

    Read the full bite: Difference between launch and async in Kotlin Coroutines

  16. Question 16 of 30

    What is the most direct consequence of calling an `async` function in Dart without using the `await` keyword?

    Show the answer

    Answer: a · The variable assigned the result will hold a `Future` object instead of the completed value.

    The card explicitly states that forgetting `await` results in receiving a `Future` object instead of the actual data, which can lead to downstream type errors. The `async` function itself still executes non-blockingly, and it doesn't immediately throw an exception or prevent execution.

    Read the full bite: Dart's async/await: Non-Blocking Code That Reads Synchronously

  17. Question 17 of 30

    For a Kotlin Coroutine task that updates a UI element and does not require a return value, which builder is most appropriate?

    Show the answer

    Answer: d · launch

    The correct choice is launch because it is designed for 'fire-and-forget' operations, such as UI updates, where a direct result is not needed and it returns a Job. Using async for such a task would create a Deferred object whose result is never awaited, potentially leading to silently swallowed exceptions.

    Read the full bite: Explain launch vs. async in Kotlin Coroutines

  18. Question 18 of 30

    You need to fetch two pieces of data in parallel inside a ViewModel and return both results to the caller. Which choice best follows structured concurrency?

    Show the answer

    Answer: a · Use async for both calls and await each Deferred before returning

    async returns a Deferred that lets you retrieve computed values with await, which is exactly what you need when results must be returned, whereas launch is fire-and-forget. Option C is tempting but wrong because injecting a custom Job breaks the parent-child relationship required by structured concurrency.

    Read the full bite: Explain the difference between launch and async in Kotlin Coroutines

  19. Question 19 of 30

    What is the primary effect of a `suspend` function when it needs to wait for a long-running operation like a network request?

    Show the answer

    Answer: b · It can pause the coroutine's execution, freeing the underlying thread to perform other work.

    A suspend function pauses the coroutine, freeing the thread it was running on for other work. It does not inherently switch threads (that's a dispatcher's job) or block the thread.

    Read the full bite: What is a `suspend` function in Kotlin?

  20. Question 20 of 30

    Which statement best describes the core trade-off when selecting a lower transaction isolation level?

    Show the answer

    Answer: d · It aims to maximize concurrent transaction execution, potentially allowing more data anomalies.

    The card states that lower isolation levels increase concurrency by using fewer locks, but this comes at the cost of allowing more types of data anomalies. Option D accurately captures this fundamental trade-off between maximizing concurrent execution and the risk of data anomalies. Option B describes the characteristics of higher isolation levels, not lower ones.

    Read the full bite: Transaction Isolation Levels: The Concurrency vs. Correctness Dial

  21. Question 21 of 30

    For which task would Node.js Worker Threads provide the most significant benefit?

    Show the answer

    Answer: c · Processing a large video file to apply a filter.

    Worker threads are specifically designed for CPU-bound operations like video processing to offload heavy computation from the main thread. I/O-bound tasks, such as database queries or network requests, are already efficiently managed by Node's event loop and do not benefit from worker threads.

    Read the full bite: Worker Threads: True Parallelism in Node.js

  22. Question 22 of 30

    What is the fundamental mechanism enabling a Kotlin suspend function to pause execution without blocking its calling thread?

    Show the answer

    Answer: d · The compiler transforms it into a state machine using Continuation-Passing Style.

    The correct answer is B because the card explicitly states the compiler performs a transformation called Continuation-Passing Style (CPS), which creates a state machine allowing the function to pause and resume. Option C is a common misconception; suspend functions do not inherently move execution to a background thread, as suspension is orthogonal to threading.

    Read the full bite: What is a Kotlin `suspend` function and how does it work?

  23. Question 23 of 30

    What is the primary advantage of employing the Node.js cluster module in a multi-core environment?

    Show the answer

    Answer: c · It allows a single Node.js application to utilize all available CPU cores for I/O-bound network operations on one machine.

    The cluster module's core purpose is to enable a single Node.js application to fully utilize all CPU cores on a *single* multi-core machine for I/O-bound tasks like network applications. It is not designed for direct memory sharing (that's worker_threads), distributing across multiple physical servers, or low-overhead IPC for frequent data exchange, as IPC overhead is noted as high.

    Read the full bite: Node.js Cluster: Scaling on a Single Machine

  24. Question 24 of 30

    Which statement best describes why Dispatchers.Unconfined is generally discouraged for common use cases?

    Show the answer

    Answer: d · Its behavior after a suspending function can lead to unpredictable thread execution.

    Dispatchers.Unconfined is discouraged because it starts on the current thread but can resume on any thread used by a suspending function, leading to unpredictable execution. This is distinct from creating new threads (which is more relevant to newSingleThreadContext) or always running on the main thread.

    Read the full bite: Coroutine Dispatchers: Telling Your Coroutines Which Thread to Use

  25. Question 25 of 30

    What is the primary effect of cancelling a CoroutineScope?

    Show the answer

    Answer: b · All coroutines that were launched within that scope are automatically cancelled.

    The core function of a CoroutineScope is to manage the lifecycle of its child coroutines; thus, cancelling the scope automatically cancels all coroutines launched within it. Option C is incorrect because existing coroutines are also cancelled, not continued, and new launches would fail rather than just being prevented.

    Read the full bite: CoroutineScope: The Parent of Your Coroutines

  26. Question 26 of 30

    In a standard CoroutineScope, if one child coroutine fails with an exception, what is the immediate effect on its siblings and the parent scope?

    Show the answer

    Answer: b · The failing coroutine cancels its siblings, and the exception then propagates up to cancel the parent scope.

    Structured concurrency with a standard Job follows an 'all-for-one' policy. An uncaught exception in one child cancels its siblings and then propagates to the parent, cancelling the entire scope. The behavior where siblings continue running is characteristic of a SupervisorJob.

    Read the full bite: Structured Concurrency in Kotlin Coroutines

  27. Question 27 of 30

    In Kotlin's Structured Concurrency, what is the default outcome if one child coroutine launched with launch throws an uncaught exception?

    Show the answer

    Answer: b · The parent scope and all its sibling coroutines are immediately cancelled.

    With a default Job, an uncaught exception in a child coroutine launched with 'launch' propagates up, cancelling the parent scope and all its other children, ensuring a "fail-fast" system. Option A is incorrect because the default behavior is not to isolate failures but to propagate them, unlike with a SupervisorJob.

    Read the full bite: Explain Structured Concurrency in Kotlin Coroutines

  28. Question 28 of 30

    Why is Python's threading module generally not recommended for speeding up CPU-bound tasks on multi-core machines?

    Show the answer

    Answer: a · The Global Interpreter Lock (GIL) prevents multiple threads from executing Python bytecode simultaneously.

    The card states that the GIL "prevents multiple threads from executing Python code at the same time," which is the fundamental reason threading cannot achieve true parallelism for CPU-bound tasks. While thread management overhead (option C) can make a program slower, the GIL is the core reason it won't speed up by utilizing multiple CPU cores.

    Read the full bite: Python Concurrency vs. Parallelism

  29. Question 29 of 30

    What is the primary reason Python's threading module can improve performance for I/O-bound applications despite the Global Interpreter Lock (GIL)?

    Show the answer

    Answer: d · The GIL is released by a thread when it enters a waiting state for an I/O operation, allowing other threads to execute Python bytecode.

    The card explains that when a thread is blocked waiting for an I/O operation, the GIL is released, allowing other threads to acquire it and execute Python bytecode, thereby improving concurrency. Option C is incorrect because the GIL is released and reacquired, not entirely bypassed.

    Read the full bite: The Python GIL: One Thread at a Time

  30. Question 30 of 30

    An Android ViewModel reads a large file from disk and parses the bytes into objects. Which dispatcher strategy is correct?

    Show the answer

    Answer: b · Perform the read on Dispatchers.IO and the parsing on Dispatchers.Default

    Blocking file reads should use Dispatchers.IO, while CPU-intensive parsing belongs on Dispatchers.Default. Using Default for the read starves its limited thread pool, and using IO for parsing misuses the on-demand thread expansion designed for blocking operations.

    Read the full bite: What is a CoroutineDispatcher and when to use Default versus IO?

Could you explain these out loud?

That is what an interview actually tests. Tezvyn gives you questions like these with what the interviewer is really checking, the answer that lands, and the mistake that ends the conversation, in the four minutes before your next meeting.

The iPhone app is on the way

We are building it. Until it lands, nothing here is held back from you: every interview card, your saved cards, streaks and the job board all work in Safari, plus hundreds of free practice quizzes of thirty questions each. Sign in and it all carries over to the app the day it arrives.

Want it as an icon? Tap Share at the bottom of Safari, then Add to Home Screen. It opens full screen and the cards you have read stay available offline.

Get it on Google PlayiPhone app coming soon