进程、线程和 CPU 核心数
# 进程、线程和 CPU 核心数
进程、线程和 CPU 核心数是理解计算机系统如何运行程序以及进行性能调优的三大基石。我们可以用一个生动的比喻来串联它们:CPU 核心数是“干活的工人”,进程是“独立的工作车间”,而线程是车间里具体“干活的工人(工人手里的具体任务)”。
下面详细拆解这三个概念:
## 1. 进程(Process):资源分配的基本单位
进程是计算机中已运行程序的实体。它是操作系统进行资源分配和调度的基本单位。
- **独立性**:每个进程都有自己独立的内存空间(包括代码段、数据段、堆、栈等)。进程 A 崩溃了,通常不会直接影响进程 B。
- **开销大**:因为进程之间是相互隔离的,操作系统在创建、销毁或切换进程时,需要分配和回收大量的内存资源,开销较大。
- **通信困难**:进程间通信(IPC)比较复杂,需要通过管道、消息队列、共享内存等专门的机制。
**生活比喻**:进程就像是一个个独立的“公司”或“车间”。每个公司都有自己的办公室、资金和物资(内存资源)。
## 2. 线程(Thread):CPU 调度的基本单位
线程是进程中的一个执行流,是操作系统进行 CPU 调度和执行任务的最小单位。一个进程至少包含一个线程(主线程),也可以包含多个线程。
- **共享资源**:同一个进程内的多个线程共享该进程的全部资源(如内存地址空间、打开的文件等)。
- **轻量级**:线程的创建、销毁和上下文切换的开销远小于进程。
- **通信方便**:因为共享内存,线程之间可以直接读写同一块内存数据进行通信,但这也带来了“线程安全”的问题(需要加锁来防止数据冲突)。
**生活比喻**:线程就像是车间里的“员工”。同一个车间(进程)里的员工可以共享车间的设备和物资,沟通起来非常方便,但如果两个人同时去操作同一台机器,就需要协调(加锁),否则会出事故。
## 3. CPU 核心数(CPU Cores):真正的物理算力
CPU 核心数是计算机硬件层面的概念,代表了 CPU 内部真正能够同时并行处理指令的物理单元数量。
- **并行处理能力**:核心数越多,代表 CPU 在同一微秒内能真正同时干的事情就越多。
- **与线程的关系**(并发 vs 并行):
- 单核 CPU:即使你的程序开了 100 个线程,单核 CPU 在任意绝对时间点上只能执行其中 1 个线程。其他线程只能排队等待。操作系统通过极快地在不同线程间切换(上下文切换),制造出“大家都在同时运行”的假象,这叫并发(Concurrency)。
- 多核 CPU:如果你有 8 个核心,那么在同一绝对时间点,CPU 可以真正同时执行 8 个线程。这叫并行(Parallelism)。
## 4. 三者的核心关系与总结
| 概念 | 核心定义 | 资源归属 | 切换开销 | 形象比喻 |
| --- | --- | --- | --- | --- |
| CPU 核心 | 物理算力单元 | 硬件 | 无 | 真正干活的工人 |
| 进程 | 资源分配单位 | 独立内存空间 | 大 | 独立的工作车间 |
| 线程 | CPU 调度单位 | 共享进程资源 | 小 | 车间里干活的员工 |
## 5. 它们是如何协作的?
当你打开一个浏览器(启动一个进程)并加载多个网页标签时,浏览器可能会为每个标签或后台任务创建多个线程。操作系统会将这些线程分发给空闲的 CPU 核心去执行。如果你的 CPU 核心数很少,而线程数非常多,CPU 就会把大量时间浪费在“线程切换”进程、线程和 CPU 核心数上,导致电脑变卡;如果 CPU 核心数充足,就能真正发挥多线程的威力,让程序飞速运行。
# 线程并发模型
我们可以把线程并发模型分为两大类来理解:
## 1. 做“各自不同的活”(功能分工型)
这是最常见的多线程模式,也被称为“主从模式”或“生产者-消费者模式”。线程之间通过分工协作来完成一个复杂的整体任务。
**特点**:每个线程有明确的职责,它们处理的任务逻辑完全不同。
**经典场景**:
- Web 服务器(如 Nginx、Tomcat):一个主线程专门负责监听端口、接收用户的网络请求(接客),然后把这些请求分发给后台的多个工作线程去处理具体的业务逻辑(如查数据库、计算数据、渲染页面)。
- 图形界面软件(如浏览器、游戏):必须把“界面渲染”和“后台计算”分开。如果只有一个线程,当你点击一个按钮触发复杂计算时,整个界面就会卡死(无响应)。所以,通常会有一个专门的“UI线程”负责响应用户点击和刷新画面,而其他的“后台线程”负责去下载文件或处理数据。
- 生产者-消费者模型:比如视频直播软件,一个线程负责从摄像头采集画面(生产者),另一个线程负责把画面压缩编码(消费者),还有一个线程负责把压缩好的数据推送到网络。
## 2. 做“一样的内容”(并行计算型)
这种模式通常用于“线程池”或“高性能计算”。当遇到海量且重复的任务时,我们会把任务拆碎,交给一群做同样事情的线程去并行处理。
**特点**:所有线程运行的代码逻辑一模一样,只是处理的数据不同。
**经典场景**:
- 线程池(Thread Pool):这是后端开发中最常见的模式。系统预先创建好 10 个“打工人”线程,它们都闲着没事干,循环等待。当有 100 个用户请求发过来时,这 10 个线程谁抢到任务就去处理谁。它们干的事情本质是一样的(解析请求 -> 查库 -> 返回),但各自处理的是不同用户的数据。
- 大数据处理与 AI 训练:比如你要给 100 万张图片打标签。你可以开启 8 个线程,每个线程都运行同样的“图片识别算法”,只是各自负责处理 12.5 万张不同的图片。这样能充分利用多核 CPU 的并行能力,极大缩短处理时间。
## 核心总结
**做不同的活**:是为了解耦,防止一个任务卡死导致整个程序崩溃,或者为了让界面不卡顿。
**做一样的活**:是为了提速,利用多核 CPU 的优势,把大量重复的工作分摊下去并行处理。
在真实的大型软件中,这两种模式往往是混合使用的。比如一个电商系统,后台可能有一个线程池(做一样的活)来处理用户的下单请求;而处理下单请求的某个线程内部,又可能会开启几个子线程,分别去异步调用“扣减库存服务”、“积分服务”和“消息推送服务”(做不同的活)。
许可协议:
CC BY 4.0