同步和异步大概了解,但一讲到阻塞和非阻塞就觉得复杂起来。
在相关文章 进程 vs 线程:技术面试第一高频问题完整总结(通过内存结构理解) 中,还可以一起查看背景概念和后续应用案例。Dispatch
你可能会想:“同步 = 阻塞、异步 = 非阻塞,不是吗?”但它们其实是不同的轴。组合后会得到四种情况,而且四种在实际中都存在。
每当谈到网络代码、async/await 或 Node.js 这样的事件循环时,就会出现这些概念。只要把两个轴真正理解清楚,就能长期使用。
本文会准确区分两个轴,并结合示例总结 2×2 组合。
先总结核心内容。
- 同步/异步轴:由谁负责任务完成 — 调用方直接处理就是同步,收到通知就是异步
- 阻塞/非阻塞轴:调用时是否立即返回控制权 — 不返回就是阻塞,立即返回就是非阻塞
- 两个轴彼此独立,因此 2×2 = 4 种组合全部存在
- 实际工作中最常见的是同步+阻塞、异步+非阻塞两种
轴 1:同步 vs 异步 — 谁负责完成?
同步(synchronous)是由调用方直接处理任务是否完成的方式。发送请求后,流程会一直受该任务限制,直到结果返回。
A 结束后执行 B,B 结束后执行 C。顺序得到保证。
异步(asynchronous)是先发出请求、继续处理其他事情,并在完成后收到通知的方式。回调、闭包和 async/await 的 continuation 都是这种“通知渠道”(POSIX aio_read)。
用餐厅来类比。同步就是点餐后站在柜台前,等餐做好再拿走。
异步则是拿着震动呼叫器,在座位上做别的事,呼叫器响了再去取餐。
轴 2:阻塞 vs 非阻塞 — 是否返回控制权
这次关注的角度不同。判断标准是被调用的函数是否立即返回控制权。
阻塞(blocking)表示调用后,调用方线程会一直被占用,直到函数结束。在此期间线程什么也做不了。
非阻塞(non-blocking)表示调用后先立即返回。如果结果还没准备好,也可以返回“还没完成”之类的状态(POSIX read)。
如果同步/异步描述的是“完成管理方式”,阻塞/非阻塞描述的就是“是否等待”。它们是不同的轴。
完整查看 2×2 组合
| 组合 | 行为 | 代表示例 |
|---|---|---|
| 同步 + 阻塞 | 等待并接收结果后继续 | 普通函数调用、基础文件 read |
| 同步 + 非阻塞 | 立即返回,并反复确认是否完成(轮询) | 在循环中持续检查非阻塞套接字 |
| 异步 + 阻塞 | 等待通知,但线程处于阻塞状态 | 启动异步 API 后立即等待结果 |
| 异步 + 非阻塞 | 发起后处理其他事情,完成时收到通知 | URLSession 回调、async/await |
同步+非阻塞可能不太直观,可以把它想成“没有震动呼叫器,却每分钟去柜台问‘好了吗?’的顾客”。
它掌握着控制权,但由自己负责完成处理,所以是同步。
异步+阻塞实际上是浪费的组合。做成异步后却立即等待结果,与同步+阻塞没有区别,只是结构更复杂。
调用异步函数后立刻调用 wait 的代码就是这种情况。
从 Swift 来看
GCD(Grand Central Dispatch)时代的 sync/async,实际上更接近于描述是否阻塞。
queue.sync 会一直占用当前线程,直到闭包结束(阻塞)。queue.async 发起任务后立即进入下一行(非阻塞)。
async/await 是一种让异步+非阻塞代码读起来像同步代码的语法。
let data = try await fetchImage() // 这里会“暂停”,但
// 线程不会被占用,而是去处理其他工作
在 await 位置,函数会暂时暂停,但线程会被释放去处理其他任务。代码读起来像同步代码一样从上到下执行,而实际行为是非阻塞的,这才是关键。
“不阻塞主线程、不陷入回调地狱,还能按顺序编写代码”就是这种语法存在的原因。
面试要点
第一步是分别用一句话区分两个轴的判断标准。
“阻塞/非阻塞关注是否立即返回控制权,而同步/异步关注调用方是自行处理完成,还是接收通知。”
接下来面对“请举出四种组合的例子”这一追问时,逐一回答表中的案例。尤其是能够解释同步+非阻塞(轮询),就说明你真正理解了两个轴。
总结
- 同步/异步:调用方直接处理完成就是同步,收到通知就是异步
- 阻塞/非阻塞:调用时不返回控制权就是阻塞,立即返回就是非阻塞
- 两个轴彼此独立,因此四种组合全部存在
- 同步+非阻塞是轮询,异步+阻塞大多是吃亏的组合
- GCD 的 sync/async 更接近于是否阻塞,而 async/await 让异步+非阻塞读起来像同步代码
- 餐厅类比:在柜台等待(同步+阻塞)、每分钟询问(同步+非阻塞)、震动呼叫器(异步+非阻塞)
来源与核验标准
- POSIX read — The Open Group · 标准・规范原文 · 核验 2026-08-17 · 依据:阻塞 I/O 与 O_NONBLOCK 行为
- POSIX aio_read — The Open Group · 标准・规范原文 · 核验 2026-08-17 · 依据:异步 I/O 请求与完成模型
- Dispatch — Apple · 官方文档 · 核验 2026-08-17 · 依据:基于队列的同步/异步任务提交

