I roughly understand synchronous and asynchronous, but blocking and non-blocking make things confusing.
In the related article Process vs. Thread: The #1 Technical Interview Question Explained Through Memory Layout, you can review the background concepts and follow-up applications. Dispatch
You might think, “Synchronous = blocking and asynchronous = non-blocking,” but these are different axes. Combining them produces four cases, and all four exist in practice.
These concepts come up whenever network code, async/await, or event loops such as Node.js are discussed. Once you understand the axes, you can apply them again and again.
This article separates the two axes precisely and explains all 2×2 combinations with examples.
Here is the key summary first.
- Synchronous/asynchronous axis: who tracks task completion — synchronous when the caller tracks it directly, asynchronous when it receives a notification
- Blocking/non-blocking axis: whether control is returned immediately after a call — blocking when it is not, non-blocking when it is
- The two axes are independent, so all 2×2 = 4 combinations exist
- The two combinations most common in practice are synchronous + blocking and asynchronous + non-blocking
Axis 1: Synchronous vs. Asynchronous — Who Tracks Completion?
Synchronous means that the caller directly tracks whether a task has completed. Once it sends a request, execution remains tied to that task until the result arrives.
When A finishes, do B; when B finishes, do C. The order is guaranteed.
Asynchronous means sending a request, moving on to other work, and receiving a notification when it completes. Callbacks, closures, and async/await continuations are all this “notification channel” (POSIX aio_read).
Consider a restaurant. Synchronous means placing an order and waiting at the counter until the food is ready.
Asynchronous means taking a pager, doing something else at your table, and picking up the food when it rings.
Axis 2: Blocking vs. Non-blocking — Is Control Returned?
This time, the perspective is different. The criterion is whether the called function returns control immediately.
Blocking means that after a call, the calling thread is tied up until the function finishes. It cannot do anything else during that time.
Non-blocking means the call returns immediately. If the result is not ready, it still returns a status such as “not ready yet” (POSIX read).
If synchronous/asynchronous describes “completion management,” blocking/non-blocking describes “whether you wait.” They are different axes.
Examining All 2×2 Combinations
| Combination | Behavior | Typical example |
|---|---|---|
| Synchronous + blocking | Wait for the result, then continue | Regular function call, basic file read |
| Synchronous + non-blocking | Return immediately and repeatedly check whether it is ready (polling) | Non-blocking socket checked continuously in a loop |
| Asynchronous + blocking | Wait for notification while the thread remains tied up | Start an asynchronous API and immediately wait for its result |
| Asynchronous + non-blocking | Send it off, do other work, and receive a notification on completion | URLSession callback, async/await |
Synchronous + non-blocking may feel unfamiliar: it is like “a customer who visits the counter every minute to ask, ‘Is it ready?’ without a pager.”
The caller retains control but tracks completion itself, so it is synchronous.
Asynchronous + blocking is effectively a losing combination. If you make something asynchronous but immediately wait for the result, it is no different from synchronous + blocking, only more complicated.
Code that calls wait as soon as it starts an asynchronous function is an example.
Looking at Swift
The sync/async terminology from the GCD (Grand Central Dispatch) era is actually closer to describing blocking behavior.
queue.sync ties up the current thread until its closure finishes (blocking). queue.async sends the work off and moves straight to the next line (non-blocking).
async/await is syntax that makes asynchronous + non-blocking code read like synchronous code.
let data = try await fetchImage() // It is 'suspended' here
// The thread is not blocked and goes to do other work
At the await point, the function pauses briefly, but the thread is released to process other work. The code reads top to bottom like synchronous code, while its actual behavior is non-blocking.
“Keep the main thread unblocked while writing sequentially without callback hell” is why this syntax exists.
Interview Takeaways
Start by distinguishing the criteria for the two axes in one sentence each.
“Blocking/non-blocking concerns whether control is returned immediately, while synchronous/asynchronous concerns whether the caller tracks completion or receives a notification.”
Then answer the follow-up, “Give an example of each combination,” with one case from the table at a time. Being able to explain synchronous + non-blocking (polling) is especially strong evidence that you understand the axes.
Summary
- Synchronous/asynchronous: synchronous when the caller tracks completion directly, asynchronous when it receives a notification
- Blocking/non-blocking: blocking when control is not returned on a call, non-blocking when it is returned immediately
- The two axes are independent, so all four combinations exist
- Synchronous + non-blocking is polling; asynchronous + blocking is usually a losing combination
- GCD’s sync/async is closer to describing blocking behavior, while async/await makes asynchronous + non-blocking code read like synchronous code
- Restaurant analogy: waiting at the counter (synchronous + blocking), asking every minute (synchronous + non-blocking), and using a pager (asynchronous + non-blocking)
Sources and Verification Criteria
- POSIX read — The Open Group · original standard/specification · checked 2026-08-17 · basis: blocking I/O and O_NONBLOCK behavior
- POSIX aio_read — The Open Group · original standard/specification · checked 2026-08-17 · basis: asynchronous I/O requests and completion models
- Dispatch — Apple · official documentation · checked 2026-08-17 · basis: queue-based synchronous and asynchronous task submission

