1. 并发模型概述:从单线程到多线程的演进

各位同学,咱们今天聊聊并发模型。说实话,我刚开始写程序那会儿,压根没想过"并发"这回事。那时候的单核 CPU,跑一个进程就挺满足。但后来,事情变了。

1.1 从单线程到多线程:为什么非变不可?

早期的服务端程序,就是一个 while 循环,挨个处理请求。你想想看,一个请求没处理完,后面的就得排队等着。这在用户量小的时候还行,一旦并发上来,响应时间直接爆炸。

我记得 2010 年左右,我参与过一个电商后台项目。上线第一天,用户一多,服务直接卡死。查了半天,发现是单线程处理请求,一个慢查询把整个线程堵住了。嗯,从那以后,我对"单线程瓶颈"有了刻骨铭心的认识。

演进路径其实很清晰:

  • 单进程单线程:简单,但吞吐量极低。一个阻塞点拖垮全局。
  • 多进程:每个请求一个进程,隔离性好,但进程创建销毁开销大,内存占用高。
  • 多线程:共享内存,轻量级切换,成为主流。但随之而来的是竞态、死锁、上下文切换开销。
  • 事件驱动/协程:用户态调度,更轻量,适合 I/O 密集型场景。

核心观点:从单线程到多线程,本质是用"复杂度"换"吞吐量"。没有银弹,只有权衡。

1.2 并发与并行的区别

这个问题,面试里被问烂了。但说实话,很多人还是搞混。我简单说:

  • 并发(Concurrency):逻辑上的"同时"。多个任务在同一个时间段内交替执行。你吃着火锅唱着歌,虽然嘴和嗓子不能同时用,但宏观上你确实在"同时"做两件事。
  • 并行(Parallelism):物理上的"同时"。多个任务在多个 CPU 核心上真正同时执行。你左手画圆右手画方,两个手各干各的。

用个图可能更直观:

并发 vs 并行 对比图 并发(Concurrency) 单核 CPU,任务交替执行 逻辑上同时,物理上串行 例:一个线程处理多个请求 并行(Parallelism) 多核 CPU,任务真正同时执行 物理上同时,需要硬件支持 例:多线程在多核上跑 ≠ 关键区别 并发关注"任务结构"——如何设计多个任务的执行方式 并行关注"执行效率"——如何利用多核加速

个人经验:我在做高并发网关时,经常遇到"并发设计没问题,但并行效率上不去"的情况。原因往往是锁竞争太激烈,导致多个核心在"抢锁"上浪费了大量时间。这时候,并发模型选对了,但并行效果没出来。

1.3 为什么需要并发模型?

你可能会问:直接用线程不就行了?搞什么模型?

我刚开始也这么想。直到有一次,我接手一个遗留系统,里面线程满天飞,new Thread() 到处都是。结果呢?

  • 线程数一多,上下文切换开销把 CPU 吃光了。
  • 共享数据没保护,竞态条件导致订单金额算错。
  • 死锁了,服务完全无响应,只能重启。

说白了,并发模型就是一套"管理并发任务的规则和模式"。它帮你回答几个关键问题:

  1. 任务怎么拆分?——是每个请求一个线程,还是用线程池复用?
  2. 数据怎么共享?——用锁?用消息传递?用无锁数据结构?
  3. 任务怎么调度?——抢占式还是协作式?
  4. 错误怎么处理?——线程挂了怎么办?任务超时怎么恢复?

没有模型,你就是在裸写并发。短期能跑,长期必崩。

避坑指南:我曾经在一个项目中,为了"性能",大量使用 synchronized 粗粒度锁。结果性能没上去,反而因为锁竞争导致吞吐量下降。后来改用读写锁 + 分段锁,才解决问题。记住:并发模型不是越复杂越好,而是越适合场景越好。

1.4 主流并发模型一览

咱们课程会深入讲解几种主流模型。这里先给个全景图:

模型 核心思想 典型代表 适用场景
线程池模型 预创建线程,任务队列分发 Java ThreadPoolExecutor 通用服务端,计算密集型
事件驱动模型 单线程事件循环,非阻塞 I/O Node.js, Netty, Redis I/O 密集型,高并发连接
Actor 模型 消息传递,无共享状态 Erlang, Akka 分布式系统,高可用场景
协程模型 用户态轻量级线程,协作式调度 Go goroutine, Kotlin coroutine 高并发,微服务
数据流模型 数据驱动计算,流水线处理 Apache Flink, Spark Streaming 大数据实时处理

每种模型都有自己的哲学。线程池模型强调"资源复用",事件驱动模型强调"非阻塞",Actor 模型强调"隔离",协程模型强调"轻量"。没有绝对的好坏,只有是否匹配你的业务场景。

我的建议:初学者不要贪多。先把线程池模型吃透,因为它是最通用的基础。然后再去学事件驱动和协程。Actor 模型和数据流模型,等你遇到分布式场景再深入也不迟。

1.5 本章小结

咱们这一章,从单线程的局限讲到了多线程的演进,理清了并发和并行的区别,也解释了为什么需要并发模型。说白了,并发模型就是帮你"管好线程、用好资源、不出 bug"的一套方法论。