Skip to content

多线程

约 874 字大约 3 分钟

2025-09-01

一个执行上下文(context of execution),每个线程有自己的执行流调用栈错误码信号掩码私有数据 线程与进程没有本质区别,对于操作系统而言,其基本单元为 COE(CPU 状态、MMU 状态、权限状态、通信状态),即一个 Task,因此进程表现为一个线程组且包含一个或多个共享资源的线程

执行流

每一个线程根据编译的汇编指令序列依次执行,这个流程称之为执行流;执行流的顺序与代码顺序可能会因为分支、跳转或是编译器对语句进行重排、处理器乱序执行的影响,可能不会与编写的代码顺序完全一致

逻辑线程与硬件线程

逻辑线程定义「任务」,于硬件线程中运行

逻辑线程

程序执行的任务逻辑,描述了任务逻辑,即怎么做,如何做

硬件线程

CPU 中的核心,对于软件来说只需关注其逻辑核心(部分 CPU 支持超线程)

线程、核心、函数的关系

线程从入口函数开始运行,期间可以调用其他函数,便形成了函数调用链 对于单一任务,可以拆分多个数据段,或是每个线程处理不同逻辑的任务实现多线程工作 核心对应具体的执行者,每个执行者在某一时刻只能执行一个线程的工作

协程

位于用户态的多执行流,无需进入内核态切换上下文,因此上下文切换的开销低

线程相关概念

时间分片

CPU 并不会一直执行某个进程,直至其结束;时间分片下 CPU 的时间会被切分为短的时间片以分配给不同的线程,每一份时间片极短,仿佛该任务独占 CPU

上下文切换

CPU 将当前任务迁走,并挑选一个新任务到 CPU 上执行的操作称为调度,而在调度过程中会发生上下文切换,即保存迁出任务的状态,加载新任务的状态 上下文切换会使用 CPU 时间,因此频繁的切换会影响 CPU 的效率

上下文信息

  • CPU 寄存器状态
    • 通用寄存器:保存临时数据,函数参数等
    • 程序计数器:保存下一条指令的地址
    • 栈指针计数器:保存该任务自己的栈的栈顶
  • 内存地址空间(进程(线程组) 切换需要,进程内共享内存空间)
  • PCB/TCB

线程同步

为什么需要线程同步?

不同的线程操作访问共享数据时,可能会发生竞争;当多个线程中存在读与写的操作,且写操作无法在一个时间轮片下完成所有操作时,其他线程就有可能读取到「半成品」

死锁

ABBA 锁

线程 1 拥有 A 锁,想要获得 B 锁,而线程 2 拥有 B 锁,想要获得 A 锁,最终导致了两线程无线等待 解决方法:使用 try-lock 实现,若无法获取到锁则释放已有的锁;对锁的获取进行排序,即对于 A、B 这两个锁,必须先获取 A 才能获取 B(或先获取 B 才能获取 A)