你还在说"协程是轻量级线程"吗?Kotlin 官方已经不这么定义了。
一、早期的说法:协程 = 轻量级线程
Kotlin 1.1 刚推出协程时,官方文档里直接写着:
"Coroutines are light-weight threads."
当时这样宣传完全合理。那几年大家还在被 Thread、AsyncTask、RxJava Scheduler、callback hell 折磨,Kotlin 需要一个最容易传播的比喻:
- 线程很贵(系统调用、栈内存、上下文切换)
- 协程很便宜(几乎零成本创建,轻松开几十万个)
于是"轻量级线程"成了最广为流传的定义。
二、现在官方怎么说的?
打开当前版本的 Kotlin Coroutines Basics 文档,你会发现措辞明显变了:
| 旧文档(1.1 时期) | 新文档(当前) |
|---|---|
| Coroutines are light-weight threads. | A coroutine is an instance of a suspendable computation. |
| 强调:lightweight、thread | 强调:suspend、non-blocking、structured concurrency |
官方不再把协程定义为"线程的轻量版",而是重新定义为:
一段可挂起的计算(suspendable computation)。
核心词从 thread 变成了 suspend。
三、为什么要改?因为"轻量级线程"容易让人误解
误解一:协程就是线程
协程不是 OS Thread,不是 JVM Thread,不参与 CPU 调度。它的底层是 Continuation(续体)+ 状态机,跟线程是完全不同的抽象层次。
误解二:协程的价值是"性能"
很多人以为协程解决的是线程性能问题。实际上,协程的首要价值是让异步代码变得可读,资源效率是附带的收益。
回调地狱:
协程写法:
代码从"跳来跳去"变回了"从上往下"。这才是协程最大的胜利。
四、协程的底层到底是什么?
Kotlin 编译器会把 suspend 函数改写成状态机。
源代码:
编译后的伪代码(简化版):
关键点:
suspend的本质是保存当前执行状态,然后 return- 恢复时从上次的
label继续执行 - 整个过程不需要额外的线程或线程栈
所以有人说:
Coroutine is not a lightweight thread. Coroutine is a lightweight continuation.
协程真正便宜的不是"线程变轻了",而是 continuation 本身就极轻——只需要保存几个局部变量和一个状态标记。
五、现在官方真正强调的东西
1. Structured Concurrency(结构化并发)
父协程取消 → 子协程全部取消。不会有"野协程"泄漏。
2. Cancellation Propagation(协作式取消)
3. Suspend 语义
suspend 关键字告诉调用者:"这个函数可能异步挂起,但你可以像同步代码一样调用它。" 这是 Kotlin 最大的语言级价值。
4. Flow / Channel
完整的异步数据流生态,已经远超"轻量级线程"的范畴。
六、总结
Kotlin 官方并没有完全删除"lightweight thread"这个说法,但已经不再把它作为核心定义。
因为协程的本质不是:
更轻的线程
而是:
- Suspend(可挂起)
- Continuation(续体/状态机)
- Structured Concurrency(结构化并发)
- Non-blocking(非阻塞)
- Async Semantics(异步语义)
所以,更准确的理解应该是:
协程不是轻量级线程,而是一种语言级的可挂起并发模型。