从内存布局看并发模型的演进
2026/1/10...大约 3 分钟
深度解析:从内存布局看并发模型的演进
0. 前情提要:内存的本质与“格子”理论
内存本质上只是操作系统(OS)管理的一堆带有编号的空白格子。它本身并没有“堆”或“栈”的概念。
规则定义形态: 当 JVM 租下 4 GB 空间并定义为**堆(Heap)**时,它建立了一套“随机存取”的规则,像仓库一样按需存放对象。
硬件驱动形态: 当物理线程从剩余内存中划走 1 MB 时,这块空间被赋予了**栈(Stack)的规则。这不是因为格子变了,而是因为 CPU 的硬件设计(SP 寄存器)要求这块空间必须像“试管”**一样运作——后进先出,极速压栈。
1. 传统模型的“地盘”争夺
在传统 Java 模型中,物理线程是昂贵的“硬装修”。
- 空间割据: 假设系统 8 GB,JVM 堆占 4 GB。剩下的内存里,OS 自己占一部分,最后剩 2 GB“自由格子”。
- 栈的占用: 每创建一个物理线程,JVM 就从这 2 GB 自由格子中取走 1 MB,并将其**结构化为“试管形态”**供 CPU 执行。
- 瓶颈: 当 2048 个“试管”占满了 2 GB 自由空间,即便 4 GB 堆内存里还有大片空白,你也开不出新线程了。
2. Node.js 与 WebFlux 的异步流派
- Node.js: 坚持单车道执行 JS,把阻塞活儿扔给底层的 C++ 线程池,保护主车道不卡死,适合 UI 和简单 I/O。
- WebFlux: 靠极少数“试管”(线程)轮转处理碎片化任务。虽然省了内存,但任务被拆得太碎,导致 Debug 时任务流断裂,很难在“试管”里追踪一个完整的业务逻辑。
3. Java 21 虚拟线程:空间与结构的魔术
虚拟线程(Virtual Threads)的核心奥义是:平时在堆里当“对象”,执行时去栈里当“结构”。
- 宿舍(堆)与工位(栈): * 静止时: 100 万个虚拟线程作为任务包,以对象的形式散落在 4 GB 堆空间 里。此时它们不占物理栈,也不遵循试管逻辑,只是普通的格子数据。
- 执行时(挂载): JVM 申请极少数物理线程(如 5 个),从堆里拿出一个任务包,瞬间将其灌入物理线程那 1 MB 的“试管”空间里。
- 转换: 只有进入“试管”的这一刻,这些数据才变成了适用于 CPU 执行的栈结构。
- 卸载: 一旦阻塞,JVM 把“试管”里的数据抽出来打包回堆,空出“试管”给下一个任务。
总结:
Node.js 是在代码层躲避阻塞;WebFlux 是在线程层压榨效率;而 Java 21 是在内存层重构了规则。 它通过把“栈结构”数据动态存放在“堆空间”里,绕过了操作系统的物理限制。这让我能用最直观的同步代码,跑出以前只有顶级架构师才能调优出来的百万级并发。
