多线程
约 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)
