一、线程的核心结构
线程是操作系统进行调度和执行的最小单位 ,它不像进程那样拥有独立的资源,而是共享进程的资源(如内存空间、文件句柄等),但有自己的核心执行上下文。一个线程的核心结构主要包含以下几部分:
| 组成部分 | 作用 |
|---|---|
| 线程 ID(TID) | 线程的唯一标识,操作系统通过它区分不同线程 |
| 程序计数器(PC) | 记录当前线程下一条要执行的指令地址 |
| 寄存器集合 | 存储线程执行过程中的临时数据(如栈指针、通用寄存器等),是线程切换的关键 |
| 栈空间(线程栈) | 线程私有的栈,用于存储局部变量、函数调用上下文(独立于其他线程) |
| 状态(运行 / 就绪 / 阻塞) | 标记线程当前的生命周期状态(如运行中、等待 CPU、等待资源) |
| 优先级 | 决定线程获取 CPU 调度的优先顺序 |
| 信号屏蔽字 | 控制线程是否响应某些信号 |
二、linux如何区分进程和线程
在 Linux 系统中,进程和线程并没有本质上的严格区分 ------Linux 把所有的执行实体(包括进程和线程)都统一抽象为 task(任务),并通过 task_struct 结构体来描述。系统区分进程和线程的核心依据是资源共享的粒度和ask_struct 的关联关系。
| 特征 | 进程(独立 task) | 线程(共享资源的 task) |
|---|---|---|
| PID 与 TGID | PID = TGID(线程组 ID),是独立线程组的组长 | PID 唯一,TGID 与线程组组长的 PID 相同 |
| 地址空间(mm_struct) | 拥有独立的 mm_struct(内存映射),不共享地址空间 | 共享同一个 mm_struct,代码、数据、堆空间完全共享 |
| 文件描述符表 | 拥有独立的文件描述符表 | 共享同一个文件描述符表 |
| 信号处理 | 拥有独立的信号处理函数集合 | 共享信号处理函数,信号会发送到整个线程组 |
| 栈空间 | 拥有独立的用户栈和内核栈 | 内核栈独立(每个线程必须有),用户栈独立(线程私有),但共享堆空间 |
| 调度属性 | 独立调度,资源隔离性强 | 共享大部分调度属性,切换开销更小 |
三、线程的分类
内核级线程(KLT)、用户级线程(ULT)、混合级线程是线程的三种核心实现模型,核心差异在于调度权归属、内核感知度和资源开销,直接决定了线程的并发性能和适用场景。
| 特性维度 | 内核级线程(KLT) | 用户级线程(ULT) | 混合级线程(Hybrid) |
|---|---|---|---|
| 内核感知度 | 完全感知 | 完全无感知 | 感知内核级线程 |
| 调度主体 | 操作系统内核 | 用户态线程库 | 线程库(用户态)+ 内核(内核态) |
| 多核并行支持 | 支持 | 不支持 | 支持 |
| 阻塞影响范围 | 仅阻塞当前线程 | 阻塞整个进程 | 仅阻塞当前映射的 ULT |
| 线程切换开销 | 高(需内核态切换) | 低(纯用户态切换) | 中(平衡两者) |
| 典型应用 | 计算密集型任务 | 简单嵌入式任务 | 通用高并发场景 |
阻塞处理:
- 内核级线程:单个线程阻塞(如 I/O 等待、sleep)时,内核会切换同进程的其他线程执行,不会阻塞整个进程。
- 用户级线程:致命缺点------若某个用户级线程发生阻塞(如 I/O阻塞、系统调用),内核会认为整个进程阻塞,导致同进程内所有用户级线程被暂停。
- 混合级线程:单个 ULT 阻塞时,线程库可以将其他 ULT 切换到空闲的 KLT 上执行,不会阻塞整个进程。
四、Amdahl 定律(阿姆达尔定律)
Amdahl 定律 是计算机体系结构中用于衡量并行化对系统性能提升上限的核心公式 ,由 IBM 工程师吉恩・阿姆达尔(Gene Amdahl)于 1967 年提出。它的核心思想是:系统性能的提升程度,取决于系统中可并行化部分的比例,以及并行处理的资源数量。
4.1 公式

新执行时间=原执行时间×((1−升级比例)+升级比例升级加速比)新执行时间=原执行时间 × ((1 - 升级比例) + \frac{升级比例}{升级加速比} )新执行时间=原执行时间×((1−升级比例)+升级加速比升级比例)
总加速比=原执行时间新执行时间=1(1−升级比例)+升级比例升级加速比总加速比 = \frac{原执行时间}{新执行时间} = \frac{1}{(1 - 升级比例) + \frac{升级比例}{升级加速比} } 总加速比=新执行时间原执行时间=(1−升级比例)+升级加速比升级比例1
4.2 公式解释
- Speedup(加速比):并行执行时间与串行执行时间的比值,值越大表示性能提升越明显。
- f(升级比例 / 可并行比例):程序中可以被并行化(或被优化加速)的部分占总执行时间的比例。
- 1−f(不可升级比例 / 串行比例):程序中无法被并行化(或无法被优化)的部分占总执行时间的比例。
- N(升级加速比 / 并行资源数):可并行部分在并行后的性能提升倍数(如核心数、处理器性能倍数)。
4.3 例题
假设希望升级一个服务器的处理器。新处理器执行服务应用程序的计算速度是原处理器的 10 倍。假定原处理器有 40% 的时间忙于计算,60% 的时间等待 I/O,进行这一升级后,所得到的总加速比为多少?
4.4 解答
-
确定参数
升级比例 f:计算部分是可以被升级加速的,占总时间的 40% → f=0.4
不可升级比例 1−f:等待 I/O 的部分无法被加速,占总时间的 60% → 1−f=0.6
升级加速比 N:新处理器的计算速度是原处理器的 10 倍 → N=10
-
代入公式:

- 计算结果:

4.5 结论
即使把计算速度提升了 10 倍,但因为整个程序有 60% 的时间都在等待 I/O(无法加速),所以整体性能只提升了约 1.56 倍。这体现了 Amdahl 定律的核心:串行瓶颈(不可升级部分)会严重限制整体性能的提升。
这个例子说明:盲目升级硬件(如提升计算速度)的收益,会被程序中无法优化的部分(如 I/O 等待)限制。
五、线程状态
线程的状态描述了线程从创建到终止的整个生命周期 ,不同操作系统对线程状态的划分略有差异,但核心逻辑一致。操作系统内核通过task_struct管理线程(或轻量级进程),核心状态分为5种,状态之间的切换由内核调度器控制。
| 状态名称 | 核心含义 | 典型触发场景 |
|---|---|---|
| 新建态(New) | 线程已被创建,但尚未被操作系统调度(未分配 CPU 资源) | 调用 pthread_create(Linux)或 CreateThread(Windows)后,线程未启动前 |
| 就绪态(Ready) | 线程已具备执行条件,等待 CPU 调度执行(已在就绪队列中) | 线程初始化完成、阻塞态恢复后,进入就绪队列排队 |
| 运行态(Running) | 线程正在 CPU 上执行,占用 CPU 时间片 | 调度器从就绪队列选中线程,分配时间片开始执行 |
| 阻塞态(Blocked) | 线程因等待资源 / 事件而暂停执行,主动放弃 CPU(移出就绪队列) | 等待 I/O 完成、获取互斥锁、调用 sleep/wait |
| 终止态(Terminated) | 线程执行完毕或异常终止,释放所有资源 | 线程函数执行结束、调用 pthread_exit、被强制杀死 |
状态切换核心流程
- 新建态 → 就绪态 → 运行态 → 终止态
- 运行态 ↔ 就绪态(时间片用完,回到就绪队列重新排队)
- 运行态 → 阻塞态 → 就绪态(等待的资源就绪后,重新进入就绪队列)