知识卡片
进程与线程的演进链条:每一步解决上一步的遗留问题
内容
操作系统里”进程”“线程”这些概念不是一次性设计出来的,而是沿着一条”发现瓶颈→设计新机制解决→新机制又暴露新瓶颈”的链条逐步演进出来的,理解这条链条能帮助判断为什么某个并发机制会长这个样子。最早的计算机没有操作系统,靠用户手工输入指令、计算机执行,大部分时间计算机都在等人输入,效率很低。批处理操作系统解决了这个问题:预先把指令写成一份”任务”清单交给计算机连续执行,不再需要人工干预,但代价是一次只能执行一个任务,如果某个任务在等待I/O设备读取数据,CPU本该空闲那段时间完全被浪费掉。为了利用这段空闲时间,”进程”被发明出来:每个任务对应一个独立的进程、有自己独立的内存空间,操作系统靠给CPU分时间片的方式在多个进程之间切换,看起来像是多进程并行运行。但多进程天生互不相关,如果两个任务需要协作,只能通过慢吞吞的”A写存储、B读存储”方式交互,于是管道、消息队列、信号量、共享存储这些进程间通信机制被设计出来,解决进程之间没法直接沟通的问题。多进程解决了任务之间并行的问题,但单个进程内部依然只能串行处理——比如一个餐馆管理进程里,排位、点菜、买单这些子任务如果严格串行,某个客人买单卡壳(比如信用卡刷不出来)会拖住后面所有客人的点菜。为了让进程内部的子任务也能并行,”线程”被发明出来:线程是进程内部共享同一份数据的子任务,操作系统调度的最小单位从进程下沉到了线程,进程转而变成资源分配的最小单位;但多个线程共享数据又带来了新问题——数据可能被同时修改而出错,于是互斥锁机制被设计出来保证数据正确性。多进程多线程本质上仍是分时系统、并非真正的时间并行,要做到真正的多任务同时执行,最终要靠让多个CPU同时工作,这就是SMP(对称多处理器,即今天常见的多核处理器)、NUMA、MPP这几种真正硬件级并行方案存在的原因。
结构图:
flowchart TB
A["批处理<br/>解决人工手动操作低效<br/>⚠️I/O等待时CPU空闲被浪费"]
A --> B["进程<br/>分时片利用CPU空闲时间<br/>⚠️进程间互不相关,无法直接协作"]
B --> C["进程间通信<br/>管道/消息队列/信号量/共享存储<br/>⚠️单进程内部仍是串行"]
C --> D["线程<br/>进程内子任务并行,共享数据<br/>⚠️共享数据带来正确性问题"]
D --> E["互斥锁<br/>保证多线程共享数据的正确性<br/>⚠️多进程多线程本质仍是分时,非真并行"]
E --> F["多CPU并行<br/>SMP/NUMA/MPP<br/>真正意义上的时间并行"]