线程
线程(thread)是操作系统能够进行运算调度的最小单位,包含在进程之内,是进程中的实际运作单位。一条线程是进程中一个单一顺序的控制流,同一进程可以并发多条线程,并共享该进程的地址空间与已打开文件等资源,仅各自保留程序计数器、寄存器和栈等运行时私用部分。由于创建、切换和销毁线程的开销低于进程,线程成为实现并发与利用多核处理器的基本手段,多线程编程也由此成为现代软件开发中的常见模型[1]。
定义
线程指程序执行过程中的一条单一顺序控制流,是操作系统进行调度和分派的基本单位。它不能脱离进程独立存在,每个进程至少拥有一个线程,程序启动时最先建立的那条线程通常称为主线程[1]。
操作系统理论把资源所有权与执行调度两项职能分开:进程作为资源的容器,持有地址空间、打开的文件和用户信息等;线程则是被调度的执行实体[2]。因此同一进程内的多条线程共享该进程的代码、全局数据和堆,但各自拥有独立的栈、局部变量、寄存器和程序计数器[3]。
在 Unix System V 和 SunOS 等系统中,线程也曾被称为轻量进程(lightweight processes),不过这一称呼后来更多用于指内核线程,用户线程才直接叫线程。
原理
线程的运作依赖处理器上下文的概念。每条线程对应一组寄存器状态、一个栈和一段可执行代码,内核在切换线程时保存当前上下文并恢复目标线程的上下文,这一过程称为上下文切换。由于同进程线程共用页表与地址空间,切换时无须更换地址空间,因此开销小于进程切换[2]。
按照调度由谁完成,线程可分为用户级线程与内核级线程两类。用户级线程由应用程序内的线程库创建和管理,内核只看到进程,因而不必陷入内核态,切换很快,但一条线程发生阻塞时整个进程都会受阻[4]。内核级线程由内核直接维护和调度,某条线程阻塞不影响同进程其他线程,代价是创建与切换需在用户态和内核态之间往返[4]。
用户线程与内核线程的对应关系常用三种模型描述:N:1 模型把多条用户线程映射到单个内核调度实体,1:1 模型让每条用户线程独占一个内核线程,N:M 模型则把 N 条用户线程复用到 M 个内核调度实体上[5]。N:1 实现简单且切换极快,但同一时刻只有一条线程能被调度,无法借助多处理器;N:M 兼顾两者,却需要用户态调度器与内核调度器之间的协调,实现复杂度最高[5]。
并行与并发是两个相关但有区别的概念:并行指多个处理器在同一时刻真正同时执行多个任务,并发指单个处理器按时间片轮转处理多个任务[3]。在线程数不超过处理器数时,多条线程可以真正并行;超过时则主要依靠轮转获得并发的效果。
发展历程
20 世纪 60 年代,操作系统中同时承担资源拥有与独立运行职能的基本单位是进程。随着计算机技术演进,进程作为资源拥有者,其创建、撤销与切换带来较大的时间和空间开销,同时对称多处理机(SMP)的出现要求系统能提供多个可并行运行的执行单位,而多进程并行的开销过大,于是需要更轻量的执行体。到 20 世纪 80 年代,能够独立运行的线程作为基本单位出现,此后通用操作系统陆续引入线程机制,并将其视为衡量现代操作系统并发能力的重要指标。
Linux 的线程支持经历了较长演变。早期内核并无真正意义上的线程,常用线程库借助进程模拟;1996 年 Linux 首次借助 clone() 系统调用获得内核级线程支持,当时使用的函数库为 LinuxThreads,采用一对一线程模型,但受信号处理与调度语义所限,并不完全符合 POSIX 标准[6]。Linux 2.6 内核引入线程组与 tgid 字段,随后以原生 POSIX 线程库(NPTL)取代 LinuxThreads,并借助 futex 机制处理线程同步,使其更贴近标准[7]。
硬件层面同样出现线程相关技术。超线程由英特尔于 2002 年在至强服务器处理器与奔腾 4 桌面处理器上首次推出,它把单个物理核心划分为两个逻辑核心,使操作系统把每个物理核心识别为两个虚拟核心,从而在一个核心上同时调度多条线程,提高处理器利用率[8]。这种技术属于硬件层面的实现,编程时无须额外改写代码,但能提供的处理能力不及多核并行[8]。
应用
线程最直接的价值在于提高处理器与输入输出资源的利用率。当某条线程因等待输入输出而让出处理器时,其他线程可以继续运行,从而减少处理器的空闲时间。在服务器端,数据库服务、网络服务和大容量计算等需要同时处理多个请求的场景,常用多线程组织并发任务[2]。
图形用户界面是另一类典型场合。程序把耗时操作放入独立线程,界面线程得以继续响应按键与绘图请求,用户无须等待当前任务完成[9]。文件读写、网络通信和图像处理等可分解且彼此依赖较少的任务,也常被拆成多条线程并行执行[8]。
在编程语言层面,线程通常以库或语言内建机制提供。Java 把多线程支持内建到语言之中,线程在对象一级得到支持,并可用 synchronized 关键字对共享内存加锁[9];其 Thread 类可视为对操作系统线程接口的进一步封装[1]。Python 的 threading 模块在单个进程内操作,所有线程共享同一内存空间[10]。
当线程创建与销毁过于频繁时,程序常改用线程池管理一组可复用线程,以减少反复建立线程的开销。
局限
多线程并不必然带来性能提升。线程本身要占用内存,开启大量线程会消耗大量内存并抬高处理器在调度上的开销,在内存紧张时反而成为负担[11]。频繁的上下文切换也会拖慢执行速度,程序并发所需的时间可能被调度开销抵消[3]。
资源共享是线程模型固有的难点。多条线程同时访问同一数据时可能产生竞争,需要借助锁、信号量等同步手段保证一致性,而多个线程相互等待对方持有的资源时可能形成死锁。为此程序设计需更谨慎,线程间通信与共享数据的处理都会增加复杂度[11]。
某些语言运行环境对线程并行设有额外限制。CPython 中的全局解释器锁使同一时刻只有一条线程执行 Python 代码,CPU 密集型任务难以靠多线程提速,此类场景更适合多进程方案;而 I/O 密集型任务仍适合用多线程处理[10]。此外,用户级线程模型下一条线程阻塞即导致整个进程阻塞,也限制了其适用范围[4]。
并行效果还受硬件与资源条件制约。当线程数超过处理器数量时,并发主要靠时间片轮转实现,并非真正同时执行[3];若并发部分仍受硬件或软件资源限制而只能串行,程序还会因额外的调度开销而变慢[3]。超线程提供的并行能力也弱于真正的多核,并可能引起资源争用和缓存冲突[8]。
参见
参考资料
- 【JavaEE初阶】一文带你了解线程、多线程基础 [引用日期2026-10-29]
- 内核线程、轻量级进程、用户线程三种线程概念解惑(线程≠轻量级进程)【转】 [引用日期2026-10-29]
- 并发 [引用日期2026-10-29]
- 操作系统中的进程和线程 [引用日期2026-10-29]
- google.com 上的网页 [引用日期2026-10-29]
- aliyun.com 上的网页 [引用日期2026-10-29]
- ic619199 [引用日期2026-10-29]
- 多线程 vs. 超线程 [引用日期2026-10-29]
- github.com 上的网页 [引用日期2026-10-29]
- threading --- 基于线程的并行 [引用日期2026-10-29]
- Java部分-9线程答案 [引用日期2026-10-29]