进程与线程

一、并发系统的第一性原理

1. 并发的本质是什么?

并发不是为了更快,而是为了更好地使用有限资源。

在任何计算系统中,都存在三种不可回避的约束:

  1. **计算资源有限**(CPU 核心、内存、I/O)
  2. **任务数量不确定**(用户请求、系统服务、后台作业)
  3. **任务执行时间不可预测**(I/O、外部事件、中断)

因此,并发系统的本质目标是:

在有限资源条件下,对多个任务的时间、状态与共享资源进行有序管理。

这直接引出并发系统必须回答的三个根本问题:

  1. **执行单元是什么?**(谁在“跑”)
  2. **如何分配 CPU?**(谁先跑、跑多久)
  3. **如何安全协作?**(如何共享而不出错)

后续所有概念,都是这三个问题的不同解法。


二、执行单元的抽象演进:进程 · 线程 · 协程

2.1 执行单元的设计哲学

执行单元的演进,本质是三种诉求之间的权衡:


2.2 进程:资源隔离的基本单位

进程不是“正在运行的程序”,而是:

一个拥有独立资源视图的执行容器。

原理层定义

设计动机

代价

进程解决的是“安全与隔离”问题,而不是“高并发”问题。


2.3 线程:共享资源下的并发执行

线程的引入不是为了节省 CPU,而是为了节省“进程的重复成本”。

原理层定义

线程是共享进程资源的执行流,是调度的基本单位。

核心特征

本质权衡

获得付出
更低创建/切换成本共享状态导致复杂性
更高并发能力同步与一致性问题

线程本质上是:用复杂性换性能。


2.4 协程:调度权下放到用户态

协程的出现不是因为线程“不够快”,而是因为“内核调度太贵、太不可控”。

原理层定义

协程是由程序显式让渡执行权的执行单元。

关键特征

本质优势

本质限制

协程的核心价值在于:控制权,而不是并行度。


2.5 执行单元统一对比(原理层)

维度进程线程协程
抽象层级资源容器执行流调度原语
资源隔离
调度者内核内核用户态
切换成本极低
设计目标安全并发可控

三、调度:有限 CPU 的分配艺术

3.1 调度的第一性问题

当多个执行单元同时就绪,而 CPU 有限时,谁先运行?运行多久?

调度的本质是一个资源分配问题,不存在绝对最优解,只有目标权衡。


3.2 调度目标的分类

系统类型核心目标
批处理系统吞吐量、周转时间
交互式系统响应时间、公平性
实时系统截止时间、可预测性

调度算法的差异,本质是目标函数不同


3.3 策略与机制分离

操作系统只负责提供“如何切换”,不决定“该切换给谁”。

这是调度设计中最重要、也最稳定的思想之一。


四、协作与约束:并发正确性的核心

4.1 并发错误的根源

所有并发错误,本质都来自:

多个执行单元,在不可预测的时序下,访问共享状态。

这导致三类问题:


4.2 临界区:共享状态的最小边界

临界区不是代码问题,而是“状态所有权”的问题。

设计原则:

  1. 同一时刻只允许一个执行单元进入
  2. 不依赖 CPU 数量与速度假设
  3. 不阻塞临界区外的执行
  4. 有限等待

4.3 同步机制的抽象分层

第一层:忙等待(时间换简单)

第二层:阻塞同步(让出 CPU)

第三层:结构化并发

第四层:避免共享

同步机制的演进趋势:从“控制访问”到“消除共享”。


五、通信模型:共享内存 vs 消息传递

5.1 两种世界观

模型核心思想
共享内存状态共享 + 同步约束
消息传递状态隔离 + 显式通信

两者不是对错,而是复杂性转移的位置不同


5.2 IPC 机制的层级关系


六、经典并发问题的统一视角

问题本质
哲学家就餐资源竞争 + 死锁
读者-写者不同访问语义
生产者-消费者速率不匹配

这些问题的价值不在解法,而在于:

暴露并发系统中不可避免的结构性矛盾。


七、从操作系统到语言运行时

7.1 为什么现代语言要“重造并发模型”?

因此出现:

并发的未来,不是更快的线程,而是更高层的抽象。


八、总结:稳定知识的沉淀

这套并发体系中,真正长期稳定的不是 API,而是:

关联内容(自动生成)