程序、进程、线程分别是什么
程序、进程、线程是操作系统里最基础的一组概念。
如果这几个概念没理顺,后面再学调度、同步、上下文切换、虚拟内存时会很容易混。
一、程序是什么
程序是静态的。
它本质上是一份还没有运行起来的代码和数据,例如一个可执行文件、一个 jar 包、一个二进制镜像。
程序本身不会主动执行,它只是“可以被执行的内容”。
二、进程是什么
进程是动态的。
它是程序运行起来之后的一个实例,除了代码本身,还包括运行状态和系统分配给它的各种资源。
一个进程通常会包含:
- 代码段
- 数据段
- 堆
- 栈
- 虚拟地址空间
- 打开的文件
- 寄存器上下文
- 各种内核管理信息
所以可以简单记成:
- 程序是静态文件
- 进程是运行中的程序实例
同一个程序可以启动多个进程。浏览器就是很典型的例子,同一个浏览器程序运行后,通常会创建多个进程来承担不同任务。
三、线程是什么
线程可以理解为进程内部的一条执行流。
一个进程里可以只有一个线程,也可以包含多个线程。多线程的意义在于,让同一个进程内部的不同任务并发推进。
线程自己会保存与执行相关的现场,例如:
- 程序计数器
- 寄存器
- 栈
- 线程状态
但线程并不独占完整资源集合,它依附于进程而存在。
四、为什么说进程是资源分配的基本单位
因为操作系统通常是以进程为边界去分配资源的。
比如:
- 这个进程的地址空间是什么
- 它有哪些页表
- 它打开了哪些文件
- 它拥有哪些内核资源
这些资源大多是挂在进程上的。
所以进程更像是资源容器或者资源拥有者。
五、为什么说线程是 CPU 调度的基本单位
CPU 真正执行的不是“进程这个概念”,而是进程中的某个线程。
调度器在运行时,通常决定的是:
- 让哪个线程先运行
- 让哪个线程暂停
- 让哪个线程继续执行
所以线程是执行和调度的最小粒度。
六、进程和线程的核心区别
最关键的区别在于:
- 进程强调资源拥有和隔离
- 线程强调执行流和调度
1. 进程之间
不同进程通常拥有独立的地址空间,彼此隔离更强。
一个进程不能直接访问另一个进程的内存,这也是为什么多进程模型天然更容易做隔离。
2. 同一进程内的线程之间
同一进程内的线程共享大部分资源,典型包括:
- 代码段
- 数据段
- 堆
- 全局变量
- 打开的文件
- 地址空间
但每个线程仍然保留自己的执行现场,典型包括:
- 栈
- 程序计数器
- 寄存器
- 线程状态
这也是为什么线程之间通信方便,但也更容易互相影响。
七、线程为什么通信方便,但更容易出问题
线程通信方便,是因为它们天然共享同一进程的地址空间。
一个线程写入共享变量,另一个线程就可以直接读到;一个线程往共享队列里塞数据,另一个线程可以直接取。
但问题也正出在“共享”上。
如果多个线程同时读写同一块共享数据,就可能出现:
- 竞态条件
- 数据不一致
- 可见性问题
- 死锁
- 活锁
所以线程虽然通信方便,但必须配合同步机制,例如互斥锁、信号量、条件变量等。
八、为什么一个线程出问题,可能拖垮整个进程
因为线程共享进程的大部分资源,尤其是共享地址空间和堆内存。
如果某个线程发生严重错误,例如:
- 非法访问内存
- 越界写
- 破坏共享数据结构
它影响的往往不是它自己那一小块局部数据,而是整个进程共享的运行环境。
这时操作系统通常会终止整个进程,而不是只终止出错线程后让其他线程继续跑。
所以多线程模型更轻量,但多进程模型隔离性通常更强。
九、并发和并行要区分
并发
指多个任务在一段时间内交替推进,看起来都在执行。
单核 CPU 上,多个进程和多个线程都可以通过时间片轮转形成并发效果。
并行
指多个任务在同一时刻真正同时执行。
这通常要求多核 CPU 支持。无论是多进程还是多线程,在多核环境下都可以并行。
因此可以说:
- 进程和线程都能实现并发
- 在多核条件下,进程和线程也都可以实现并行
十、总结
面试里如果问“进程和线程有什么区别”,可以回答:
进程是资源分配的基本单位,拥有独立的地址空间和系统资源;线程是 CPU 调度的基本单位,是进程内部的一条执行流。同一进程内的线程共享代码段、数据段、堆和打开的文件等资源,但每个线程有自己独立的栈、寄存器和程序计数器。相比进程,线程的创建、切换和通信开销通常更小,但由于共享内存,也更容易出现同步和线程安全问题。
