1. 进程与线程
1.1 背景介绍
1950 年代,计算机系统通常是单任务的。早期计算机一次只能执行一个程序,需要人工切换。这种设计简单但效率低下。
1960 年代,多任务系统的概念开始萌芽。早期的大型机操作系统如 IBM 的 OS/360 引入了分时技术,允许多个用户同时使用计算机资源。虽然计算机实际一次只能干一件事,但靠这种'闪电式切换',用户感觉电脑在同时处理多个任务。
1970 年代,Unix 操作系统诞生,采用了多任务设计。Unix 通过进程调度和时间片轮转机制,允许多个程序并发执行。这一设计成为现代多任务系统的基础。
**单任务 (进程) 系统:**同一时间只能运行一个程序或任务,任务必须按顺序完成。用户需等待当前任务结束后才能启动新任务。系统资源由一个任务独占,缺乏并发能力,适用于简单应用场景。
**多任务 (进程) 系统:**允许同时运行多个程序或任务,通过时间片轮转或优先级调度实现并发。
- **协同式:**应用程序需要主动释放 CPU 资源。设计简单,但稳定性较差。
- **抢占式 (现代主流):**由操作系统强制分配资源。操作系统可以强制中断任务,确保系统响应能力,进一步提高了并发性能。现代操作系统如 Windows、Linux 均采用抢占式多任务,支持更高效的资源利用和用户体验。
1.2 进程/任务
**进程 (Process)/任务 (Task):**进程是计算机中正在运行的程序的实例 (应用程序与进程的关系近似于 Java 中类和对象的关系),是操作系统进行资源分配的基本单位。
- 应用程序 ≈ 类的代码定义 (静态模板)
- 进程 ≈ 类的运行时实例/对象 (动态实体) 打开任务管理器,这里显示的每一个运行中的 exe(可执行文件),就叫做进程。
当一个进程被创建的时候,操作系统会为它创建一个或多个 PCB(Process Control Block 进程控制块),类似 C 语言的结构体/Java 中的类,PCB 里面会存放该进程的各种属性:
- **状态:**就绪状态 (进程的资源准备完成,随时可以运行)、运行状态 (正在运行)、阻塞状态 (当进程等待某个事件时暂停执行)、终止状态 (进程执行完毕或被终止,操作系统会释放进程占用的资源)。
- **优先级:**当存在多个进程时,优先级高的进程优先执行,优先级低的进程需要等待。
- **记账信息:**记录进程已使用的系统资源,如 CPU、内存等设备的使用情况。
- **上下文信息:**进程在被调度执行前的状态信息,以便进程可以从上次暂停的地方继续执行。
**文件描述符表:**文件描述符表通常是一个数组或链表,每个节点对应一个文件描述符,进程通过文件描述符来访问文件,实现进程对文件的增删查改等操作。
**内存指针:**指向的空间就是该进程创建时所申请的内存空间,指明了这个空间中哪些位置存放数据,哪些位置存放指令/代码。
**PID:**进程的 id,可以认为是进程的身份标识,每个进程的 id 是独一无二的,不能重复。
1.3 进程优缺点与线程
优点:
- **独立性:**每个进程拥有独立的地址空间和资源,一个进程崩溃不会直接影响其他进程的运行,提高了系统的稳定性。
- **资源隔离:**操作系统为每个进程分配独立的资源 (如内存、文件描述符等),避免资源竞争和冲突,增强了安全性。
缺点:
- **资源开销大:**创建和销毁进程需要分配独立的地址空间和资源,上下文切换涉及保存和恢复大量寄存器状态,性能损耗较高。
- **PCB 管理:**创建进程需连接各个进程,利用链表或者其他数据结构将 PCB 连接起来;删除进程时需将该进程的 PCB 从链表中移除。
**线程 (Thread)/轻量级进程:**由操作系统调度,不用额外分配资源,是操作系统调度执行的基本单位。一个进程可以包含多个线程,所有线程共享进程的资源 (由线程控制块 TCB 管理),但每个线程拥有独立的执行栈和程序计数器。
优点:
- **轻量级:**线程的创建、切换和销毁比进程更高效。
- **并发执行:**多线程允许程序在同一时间内执行多个任务,提高 CPU 利用率。
- **共享资源:**线程可以直接访问所属进程的全局变量、堆内存等。
缺点:
- **稳定性风险:**单个线程的崩溃可能导致整个进程终止,因为线程间缺乏隔离性。
- **资源竞争与同步问题:**线程共享同一进程的内存空间和资源,多个线程同时访问共享数据时可能引发竞争条件,导致数据不一致。必须使用锁、信号量等同步机制,增加了编程复杂度,且不当使用可能引发死锁或性能下降。


