当前位置: 首页 > news >正文

Linux C/C++ 学习日记(29):IO密集型与CPU密集型、CPU的调度与线程切换

注:该文用于个人学习记录和知识交流,如有不足,欢迎指点。

一、IO密集型与CPU密集型的定义

对比维度IO 密集型操作CPU 密集型操作
定义操作过程中主要依赖输入 / 输出(IO)交互,CPU 大部分时间处于等待 IO 完成的状态(如等待磁盘读写、网络数据传输等)。操作过程中主要依赖 CPU 进行计算处理,CPU 持续处于高负载状态,IO 操作极少或耗时极短。
核心特征IO 操作频繁(如读写文件、网络通信);CPU 利用率低;任务执行时间主要消耗在 IO 等待。计算任务繁重(如复杂运算、逻辑处理);CPU 利用率高(接近 100%);执行时间主要消耗在计算。
C/C++ 典型例子

1. 文件读写(fread/fwriteifstream/ofstream

2. 网络数据收发(socketrecv/send

3. 数据库交互(通过 API 执行查询 / 写入)

1. 大规模数学计算(矩阵乘法、数值模拟)

2. 数据加密 / 解密(AES、RSA 算法实现)

3. 复杂算法处理(千万级数据排序、图形渲染计算)

CPU 使用率较低(大部分时间等待 IO,CPU 空闲)较高(持续满负载运行,充分占用 CPU 资源)
等待时间占比高(IO 等待时间占总执行时间的绝大部分)低(几乎无 IO 等待,总执行时间主要为计算时间)
资源瓶颈受限于 IO 设备性能(如磁盘读写速度、网络带宽)受限于 CPU 处理能力(如核心数量、主频、缓存大小)

二、IO密集型场景的解决方案

在 C/C++ 中处理 IO 密集型操作(如文件读写、网络通信、数据库交互等)的核心目标是避免CPU阻塞在IO 等待的时间里提高 CPU 利用率,并高效处理并发 IO 任务。以下是常见的解决方案及适用场景:

1. 非阻塞 IO + IO 多路复用(一般用于单线程)

单线程中、传统阻塞 IO 会导致进程 / 线程在 IO 操作时挂起(等待数据就绪),浪费 CPU 资源。非阻塞 IO 配合 IO 多路复用可解决这一问题。

(注意:要想不浪费CPU资源,你当然可以设置多个线程,当线程阻塞时,如果线程数大于内核数时,CPU会释放出去给需要的线程,但是注意线程的数量是有限制的(在Linux中每个线程占8M空间),一般应用于fd数量很少的时候,在高并发场景中我们不会采用一IO一线程的形式!!!)

1.1 非阻塞 IO

通过fcntlioctl将文件描述符(fd)设置为非阻塞模式,此时调用read/write等 IO 函数时:

  • 若数据未就绪(或缓冲区满),函数会立即返回错误(EAGAIN/EWOULDBLOCK),而非阻塞等待;
  • 进程可继续执行其他任务,避免闲置。

1.2 IO 多路复用(核心)

用于同时监控多个 IO 流的就绪状态(可读 / 可写 / 异常),避免对每个 IO 流单独轮询,大幅提升效率。常见实现:

机制特点适用场景
select支持跨平台,但 fd 数量有限(默认 1024),每次调用需复制 fd 集合,效率低简单场景、低并发
poll突破 fd 数量限制,但仍需轮询所有 fd,高并发时效率下降中等并发、跨平台需求
epollLinux 专属,事件驱动(只关注活跃 fd),无 fd 数量限制,效率极高高并发场景(如服务器)
kqueueBSD/macOS 专属,类似 epoll,支持更多事件类型(如文件修改)BSD/macOS 系统的高并发场景

(我之前写了一篇IO多路复用的代码实现的博文,可以去找一找)

1.3 总结:

维度具体内容
核心原理

1. 非阻塞 IO:通过fcntlioctl将文件描述符(fd)设为非阻塞模式,IO 操作未就绪时立即返回错误(EAGAIN/EWOULDBLOCK),不阻塞进程;

2. IO 多路复用:通过内核机制(select/poll/epoll/kqueue 等)同时监控多个 fd 的就绪状态(可读 / 可写 / 异常),仅处理活跃 IO 流。

解决的问题传统阻塞 IO 中,进程 / 线程会因等待 IO 而挂起,导致 CPU 资源浪费;单线程无法高效处理大量并发 IO 流的问题。
优点

- 避免进程 / 线程阻塞等待 IO,CPU 利用率高;

- 事件驱动模式,仅处理就绪的 IO 流,减少无效操作,效率高;

- epoll/kqueue 支持无上限监控 fd,适配高并发场景。

缺点

- select:默认 fd 上限 1024(调整意义有限),每次调用需复制 fd 集合,高并发下效率低;

- poll:无 fd 数量限制,但需轮询所有 fd,高并发时效率随 fd 数量增加而下降;- 编程复杂,需手动处理非阻塞 IO 逻辑和事件回调,易出现 “回调地狱”。

应用场景

- 高并发网络服务(如 Web 服务器、网关、即时通讯服务器);

- 需要同时处理大量 IO 流(如 thousands 级以上连接)的场景。

注意事项

- 高并发场景优先选择 epoll(Linux)或 kqueue(BSD/macOS),避免使用 select/poll;

- 需熟练处理非阻塞 IO 的返回值(如区分EAGAIN与真正的错误);

- 事件回调逻辑需简洁,避免阻塞事件循环。

2. 多线程 / 线程池

IO 密集型任务中,CPU 大部分时间处于空闲(等待 IO),因此可通过多线程并行处理多个 IO 任务,利用 CPU 多核资源。

注意:当线程阻塞时,CPU会释放,但是线程的数量是有限制的

a. 在Linux中每个线程占8M空间

b. 过多线程会导致上下文切换开销激增。

所以线程一般应用于fd数量很少的时候,在高并发场景中我们不会采用一IO一线程的形式!!!

2.1 核心思路

  • 每个线程处理一个独立的 IO 流(如一个网络连接、一个文件);
  • 当线程阻塞在 IO 时,其他线程可继续运行,避免 CPU 闲置。

2.2 线程池优化

频繁创建 / 销毁线程会带来开销,线程池通过预先创建固定数量的线程,循环处理任务队列中的 IO 任务,减少开销:

2.3 总结:

维度具体内容
核心原理

1. 多线程:每个线程独立处理一个 IO 流(如一个网络连接、一个文件),当线程因 IO 阻塞时,CPU 自动调度其他就绪线程运行;

2. 线程池:预先创建固定数量的线程,循环从任务队列中获取 IO 任务并处理,减少线程创建 / 销毁的开销。

解决的问题单线程串行处理多个 IO 流时效率低下的问题,通过多核 CPU 并行处理 IO 任务,提高整体吞吐量。
优点

- 利用多核 CPU 并行处理,提升 IO 任务吞吐量;

- 基于同步阻塞 IO 模型,编程逻辑简单,开发和维护成本低;

- 线程池避免频繁创建 / 销毁线程的开销,适合任务频繁的场景。

缺点

- 线程栈内存占用大(Linux 默认 8MB,可调整但仍有下限),IO 流过多时易导致内存压力;

- 线程上下文切换为内核级操作,开销高(约几微秒),线程数量过多会抵消并行收益;

- 线程间共享数据时易出现锁竞争,导致核心阻塞。

应用场景

- IO 流数量较少的场景(如几十到几百个连接 / 文件);

- 任务逻辑简单、IO 阻塞时间较长的场景(如少量文件批量读写、低并发数据库交互)。

注意事项

- 线程数量建议控制在 “CPU 核心数 ×2” 以内,避免过多线程导致切换开销激增;

- 可通过pthread_attr_setstacksize调整线程栈大小,减少内存占用;

- 减少线程间共享数据,优先使用无锁结构或线程本地存储,避免锁竞争。

3. 协程(轻量并发)

(关于协程的实现我会在后续博文详细介绍)

协程是用户态的 “轻量级线程”,在 IO 操作时可主动挂起,让出 CPU 给其他协程,避免线程上下文切换的开销,适合处理海量并发 IO(如十万级网络连接)。

3.1 C++ 中的协程

  • C++20 引入std::coroutine,但需配合编译器支持(如 GCC 10+、Clang 15+);
  • 第三方库:Boost.Coroutine、libco(腾讯)等,封装了协程切换逻辑。

3.2 优势

  • 协程切换成本远低于线程(无需内核参与);
  • 单线程可运行上万协程,高效处理大量 IO 任务。
  • 用同步的代码风格写异步逻辑

(注意:协程的切换通常搭配epoll实现)

3.3 总结:

维度具体内容
核心原理

协程是用户态的轻量级并发单元,拥有独立的栈空间但由用户态调度;

当执行 IO 操作时,协程主动挂起(用户态切换,无需内核参与),让出 CPU 给其他协程;

依赖底层 IO 多路复用(如 epoll)监控 IO 就绪状态,当 IO 就绪时唤醒对应的协程。

解决的问题多线程在高并发场景下内存占用大(线程栈)、上下文切换开销高的问题,支持海量 IO 流(十万级以上)的高效并发处理。
优点

- 协程切换为用户态操作,开销极低(约几十纳秒,仅为线程切换的 1/100~1/1000);

- 单线程可承载上万甚至几十万协程,支持海量并发 IO;

- 支持用同步代码风格编写异步逻辑,避免 “回调地狱”,可读性和可维护性高。

缺点

- 需依赖底层 IO 多路复用(如 epoll)实现 IO 就绪通知,否则协程挂起后无法被唤醒;

- 协作式调度,若某协程执行 CPU 密集型操作(长时间不挂起),会阻塞同一线程内的其他协程;

- 依赖第三方库(如 Boost.Coroutine、libco)或 C++20 标准协程(编译器支持有限,使用门槛高)。

应用场景

- 十万级以上海量并发 IO 场景(如高并发客户端、分布式爬虫、微服务网关);

- 每个任务包含多次 IO 等待的场景(如多次数据库查询、多步网络请求)。

注意事项

- 必须与 IO 多路复用(如 epoll)配合使用,否则无法发挥高效并发能力;

- 避免在协程中执行长时间 CPU 密集型操作,需主动挂起让出 CPU;

- 根据开发环境选择合适的协程实现(优先成熟第三方库,C++20 标准协程需确认编译器支持)。

三、CPU密集型的解决方案

在 C/C++ 中,CPU 密集型操作(如数值计算、图像处理、加密解密、复杂算法推理等)的核心瓶颈是CPU 计算能力,解决方案的核心目标是最大化利用 CPU 资源(如多核并行、指令级优化、减少计算冗余等)。以下是具体方案及适用场景:

1.多线程并行(利用多核 CPU)

现代 CPU 普遍为多核架构,单线程只能利用一个核心,多线程可将任务拆分到多个核心并行执行,直接提升计算吞吐量。

1.1 核心思路

  • 任务拆分:将 CPU 密集型任务按逻辑拆分为独立子任务(如分块处理数组、分片计算矩阵),每个子任务由一个线程执行;
  • 线程数控制:线程数通常设置为CPU 核心数(或核心数 ±1),避免过多线程导致上下文切换开销抵消并行收益(CPU 密集型任务中,线程切换成本极高:当线程数大于内核数时,如果每个线程都需要CPU,那么CPU会进行轮询。轮询的时间成本高于CPU实际计算的时间)。

2.2 实现方式

  • 原生线程(pthread/C++11 thread):手动创建线程并分配任务,适合简单场景。

  • 线程池:避免频繁创建 / 销毁线程的开销(尤其任务短而多的场景),通过预先创建固定数量的线程循环处理任务队列。适合任务粒度小、动态生成的场景(如批量图像处理)。

2.3 注意事项

  • 避免锁竞争:CPU 密集型任务中,线程间若频繁竞争锁(如共享数据写入),会导致大量核心阻塞,严重降低性能。建议:
    • 尽量使用无锁数据结构(如std::atomic)或线程本地存储(TLS)
    • 拆分任务时让数据无重叠(每个线程处理独立数据块),减少共享。
  • 负载均衡:确保子任务计算量均匀,避免 “某线程早结束,其他线程仍在忙碌” 的情况(可通过动态任务分配优化,如 TBB 的parallel_for)。

2.4 总结:

维度具体内容
核心原理

基于多核 CPU 架构,将 CPU 密集型任务按逻辑拆分为独立子任务(如数据分块、计算分片),通过多线程将子任务分配到不同 CPU 核心并行执行;

线程由操作系统内核调度,当线程数与核心数匹配时,可最大化利用多核计算能力。

解决的问题单线程只能利用单个 CPU 核心,无法发挥多核架构的计算潜力,导致 CPU 密集型任务(如数值计算、图像处理)执行效率低下的问题。
优点

- 高效利用多核资源:通过并行计算直接提升吞吐量,理论上 N 核 CPU 可实现近 N 倍加速(忽略任务拆分开销);

- 线程通信成本低:线程共享进程地址空间,可直接访问共享内存(需同步机制),数据交互效率高于进程间通信;

- 线程池优化:预先创建线程减少频繁创建 / 销毁的开销,适合短任务、动态生成任务的场景。

缺点

- 上下文切换开销高:当线程数超过 CPU 核心数时,内核需频繁切换线程(保存 / 恢复寄存器、栈等状态),每次切换约几微秒,会抵消并行收益;

- 同步成本风险:线程共享数据时需锁或原子操作,频繁锁竞争会导致核心阻塞(“串行化”),严重降低性能;

- 资源限制:每个线程默认栈空间较大(Linux 约 8MB),过多线程会占用大量内存。

应用场景

- 可拆分为独立子任务的 CPU 密集型操作:如大数组运算、矩阵乘法、图像分块处理、批量加密解密;

- 任务粒度适中且可动态生成的场景:如实时视频帧处理、批量数据清洗与转换。

注意事项

- 线程数控制:通常设为 “CPU 核心数” 或 “核心数 ±1”,避免线程数超过核心数导致切换开销激增;- 减少共享与锁竞争:优先采用 “数据无重叠拆分”(每个线程处理独立数据块),必要时用std::atomic(原子操作)或线程本地存储(TLS)替代锁;

- 负载均衡:确保子任务计算量均匀(如通过动态任务分配,如 TBB 的parallel_for),避免 “部分线程闲置、部分线程忙碌”。

2. 多进程并行(隔离性与多核利用)

多进程与多线程的核心区别是内存隔离(进程间不共享地址空间),适合以下场景:

  • 任务稳定性要求高(单个进程崩溃不影响其他进程);
  • 利用操作系统的 CPU 调度(避免线程库调度的局限性)。

2.1 实现方式

  • 通过fork(Linux)或CreateProcess(Windows)创建子进程,通过进程间通信(IPC) 传递数据(如管道、共享内存、消息队列)。
  • 共享内存(如shmget/mmap)是 CPU 密集型任务的优选 IPC 方式(避免数据拷贝开销)。

2.2 优劣

  • 优势:隔离性好,适合不稳定任务;可利用操作系统调度均衡负载。
  • 劣势:IPC 开销高于线程间共享内存;进程创建 / 销毁成本高于线程。

2.3 总结:

维度具体内容
核心原理通过创建多个独立进程(如 Linux 的fork、Windows 的CreateProcess),将 CPU 密集型任务拆分到不同进程,利用多核 CPU 并行执行;进程间内存隔离(不共享地址空间),需通过进程间通信(IPC)传递数据或同步状态。
解决的问题

- 单线程进程无法利用多核 CPU,导致 CPU 密集型任务效率低下;

- 多线程方案中 “线程崩溃可能导致整个进程崩溃” 的稳定性风险,以及线程库调度在某些场景下不如系统级进程调度灵活的局限性

优点

- 隔离性强:进程拥有独立地址空间,单个进程崩溃(如内存越界、断言失败)不会影响其他进程,适合稳定性要求高的任务(如异构计算节点、第三方不可靠模块);

- 调度更灵活:可利用操作系统原生调度机制(避免线程库调度的局限性),在复杂负载下可能获得更均衡的核心利用;

- 资源隔离:进程间内存、文件描述符等资源独立,可避免线程间的资源竞争(如堆内存碎片影响)。

缺点

- IPC 开销高:进程间数据交互需通过管道、消息队列、共享内存等方式,其中共享内存虽高效但需手动管理同步,其他方式(如管道)存在数据拷贝开销,效率低于线程间直接共享;

- 管理成本高:进程创建 / 销毁比线程更耗时(涉及地址空间初始化、页表创建等),不适合短任务频繁生成的场景;

- 内存占用高:每个进程需独立加载代码、数据,重复占用内存(如相同库的代码段在多进程中可能被共享,但堆 / 栈独立)。

应用场景

- 稳定性优先的 CPU 密集型任务:如分布式计算节点(单个节点崩溃不影响集群)、集成第三方不稳定算法(如实验性模型推理);

- 需资源隔离的场景:如多用户计算任务(避免用户间资源干扰)、对内存泄漏敏感的长期运行任务;

- 利用系统级调度优势的场景:如跨 NUMA 节点的大规模计算(进程更易绑定到特定 NUMA 节点)。

注意事项

- 优先选择高效 IPC:CPU 密集型任务中,推荐用共享内存(如mmapshmget)传递数据,减少拷贝开销,配合信号量或原子操作实现同步;

- 进程数控制:与线程类似,进程数建议不超过 CPU 核心数(避免调度开销),或根据 NUMA 节点数合理分配;

- 避免重复初始化:通过共享库或预加载数据减少多进程的重复初始化开销(如提前加载模型权重到共享内存)。

四、线程的状态

状态名称定义(核心特征)触发条件(进入该状态的原因)转换方向(可进入的其他状态)
新建(New)线程已被创建(如通过pthread_createstd::thread),但尚未启动(未调用start或未执行)。调用线程创建函数(如pthread_create)后,线程对象初始化完成但未开始执行。调用启动接口(如std::thread::joinable状态下开始执行)后,进入就绪状态
就绪(Ready)线程已启动,具备执行条件(CPU 资源除外),等待操作系统调度分配 CPU 时间片。

线程新建后启动;或阻塞状态结束(如 IO 完成、锁释放);

或被抢占后重新进入就绪队列。

被操作系统调度获得 CPU 时间片后,进入运行状态
运行(Running)线程正在 CPU 核心上执行指令,占用 CPU 资源。从就绪状态被调度器选中,获得 CPU 时间片。时间片耗尽或被高优先级线程抢占,回到就绪状态;或因等待资源(如锁、IO),进入阻塞状态;或执行完毕,进入终止状态
阻塞(Blocked)线程暂时停止执行,放弃 CPU 资源,等待特定条件满足(如 IO 完成、锁释放、信号通知)。

1. 等待互斥锁(如pthread_mutex_lock未获取到锁);

2. 执行 IO 操作(如read等待数据);

3. 调用阻塞式同步接口(如pthread_cond_wait等待条件变量)。

等待的条件满足(如锁释放、IO 完成)后,进入就绪状态
等待(Waiting)阻塞状态的细分,线程无超时等待某个事件(需被其他线程显式唤醒)。(部分模型中独立为状态)调用无超时等待接口(如pthread_cond_waitstd::condition_variable::wait)。被其他线程唤醒(如pthread_cond_signal)后,进入就绪状态
超时等待(Timed Waiting)阻塞状态的细分,线程有超时等待某个事件(超时后自动唤醒)。(部分模型中独立为状态)调用带超时的等待接口(如pthread_cond_timedwaitsleepstd::this_thread::sleep_for)。超时时间到达或被提前唤醒后,进入就绪状态
终止(Terminated)线程执行完毕(如函数返回)或被强制终止(如pthread_cancel),生命周期结束。

1. 线程函数正常返回;

2. 调用终止接口(如pthread_exit);

3. 被其他线程取消(如pthread_cancel)。

无后续状态转换,线程对象可能保留(如std::threadjoinable状态需joindetach释放资源)。

说明:

  1. 状态划分的灵活性:部分系统(如 Linux)将 “就绪” 和 “运行” 合并为 “可运行(R)” 状态(内核视角下,两者均为就绪队列中的任务,仅运行状态是当前占用 CPU 的任务)。
  2. 阻塞状态的细分:“等待”“超时等待” 是阻塞状态的特殊场景,核心都是线程放弃 CPU 等待资源,部分模型中会将其独立为状态以更清晰描述等待类型。
  3. 核心逻辑:线程状态转换的核心是”是否需要CPU“ “是否占用 CPU” 和 “是否等待资源”,从新建到终止的生命周期围绕这两点展开。

总的来说:线程的状态影响着操作系统是否分配CPU给它!!!

五、CPU调度情况

1.线程数不同时

维度线程数 ≤ CPU 内核数线程数 > CPU 内核数
CPU 利用率高,每个线程可在独立内核上并行执行,无闲置核心理论上仍为 100%,但实际因上下文切换开销,有效计算时间被占用,实际有效利用率下降
上下文切换开销低,线程间切换主要为CPU的主动让出(如阻塞、线程结束等等)高,内核需频繁切换线程(保存 / 恢复线程状态),切换开销占比显著增加
任务吞吐量随线程数增加线性提升(接近内核数时达到峰值)吞吐量先增后减,线程数超过内核数后,因切换开销抵消并行收益,吞吐量开始下降
资源消耗(内存等)低,每个线程栈空间(如 Linux 默认 8MB)总消耗可控高,过多线程的栈空间、内核调度数据结构会占用大量内存,可能引发内存压力
适用场景CPU 密集型任务(如数值计算、图像处理),需最大化核心利用率IO 密集型任务(如网络通信、文件读写),线程因 IO 阻塞时可让出 CPU 给其他线程
性能表现响应时间稳定,无额外调度延迟响应时间波动大,调度延迟增加(线程需等待 CPU 时间片)

2. 抢占式调度

项目具体内容
核心结论当线程数 > CPU 内核数时,操作系统对线程的调度属于抢占式调度
原因分析

现代操作系统(如 Linux、Windows)的线程调度机制默认是抢占式的:

线程数超过 CPU 内核数时,多个线程需共享有限的 CPU 核心,操作系统会为每个线程分配时间片(一段可执行的时间);时间片耗尽后,操作系统会主动中断当前线程(抢占其 CPU 使用权),并切换到下一个线程执行,以保证所有线程公平获得 CPU 资源,避免某线程长期占用 CPU 导致其他线程 “饥饿”。

具体表现

- 每个线程会被分配时间片(如 Linux 默认时间片约为几毫秒),时间片内线程可独占一个 CPU 核心执行;

- 时间片耗尽后,操作系统会强制切换到下一个线程,即使当前线程的计算任务未完成。

补充说明

- 抢占式调度是内核级的,由操作系统内核主动控制,与线程是否 “需要 CPU” 无关,只要线程处于就绪状态,就可能被调度器抢占或分配 CPU 时间

- 若线程因 IO 操作阻塞(如网络读写),会主动让出 CPU(属于 “协作式让出”),但整体调度机制仍为抢占式(其他就绪线程会被抢占式调度执行)。

3. 非抢占式调度

项目具体内容
核心结论当线程数 ≤ CPU 内核数时,操作系统对线程的调度以 “非抢占为主,必要时抢占”(多数场景下线程可在分配的核心上持续执行,减少强制切换)。
原因分析

现代操作系统虽默认采用抢占式调度机制,但此时线程数不超过核心数,每个线程可分配到独立的 CPU 核心,无需共享核心资源

- 若线程均为 CPU 密集型且优先级相同,操作系统通常不会主动抢占,允许线程在核心上持续执行(减少切换开销);

- 仅在特殊场景(如高优先级线程就绪、当前线程触发中断或阻塞)时,才会触发抢占式切换。

具体表现

- 线程可在分配的 CPU 核心上 “长时运行”,时间片限制较宽松(甚至不严格耗尽时间片),上下文切换极少;

- 若某线程因 IO 操作阻塞或主动让出 CPU(如yield),操作系统会调度其他就绪线程到空闲核心,此时切换属于 “协作式让出” 而非强制抢占;

- 高优先级线程就绪时,仍会抢占低优先级线程的核心(保证实时性)。

补充说明

- 此场景下 CPU 利用率接近 100%(无闲置核心),且上下文切换开销极低,适合 CPU 密集型任务(如数值计算、图像处理);

- “非抢占为主” 不代表完全无抢占,操作系统仍会通过抢占机制保证高优先级任务的响应性(如实时线程、中断处理);

- 若线程数小于核心数,空闲核心会处于 “idle” 状态,操作系统可能将线程迁移到空闲核心以平衡负载(非抢占,属于主动调度优化)。

注意:本质上还是采取抢占式(还是有时间片的设置),只是每个线程可以得到单独的CPU核心,时间片很长罢了!!!表现为操作系统不频繁调度CPU资源。

六、CPU调度与线程切换的关系

线程切换是操作系统进行 CPU 调度时的核心操作之一,二者紧密关联但不完全等同。

具体关系拆解:

  • CPU 调度(Scheduling) 是一个决策过程:操作系统的调度器根据策略(如优先级、时间片、公平性等),从就绪队列中选择下一个要在 CPU 上执行的线程。例如:当线程时间片耗尽、被高优先级线程抢占、或主动阻塞时,调度器需要决定 “接下来让哪个线程运行”。

  • 线程切换(Context Switch) 是执行过程:当调度器选定下一个线程后,操作系统会实际执行 “从当前线程切换到目标线程” 的动作 —— 保存当前线程的状态(寄存器、程序计数器、栈指针等),加载目标线程的状态,让其在 CPU 上继续执行。

总结:

线程切换是 CPU 调度过程中 “执行决策” 的关键步骤,没有线程切换,调度器的决策无法落地;而 CPU 调度则包含了 “选择线程” 和 “执行切换” 的完整逻辑。因此,线程切换可以理解为操作系统 CPU 调度机制中最核心的操作环节。

七、要点(核心总结)

1. IO密集型、CPU密集型

IO密集型表现为频繁IO等待(非本线程处理数据):在高性能网络中、我们需要做到不阻塞,避免浪费CPU性能(可以采用非阻塞IO加epoll、多线程、协程)

CPU密集型表现为频繁数据处理(本线程处理数据):我们需要做到充分利用CPU的核数、因为一线程只能对应一核,我们可以采用多线程(注意线程数小于等于核数,避免线程切换开销)、多进程的处理方案。

2. CPU的调度情况

线程的状态和个数与系统对CPU资源的调度息息相关:
我们必须理解线程数的设置如何影响CPU调度的频率、同时理解操作系统是如何根据线程状态来进行CPU资源的分配的!!!

3. 以上的知识有助于后面理解协程

大家一定要理解上面这些,因为内核的操作开销都是比较大的(我们必须想办法降低开销)。

线程的数量的限制都是为了性能:线程数量大了、占用内存大、同时切换开销大(延迟高、不适合高并发IO场景)、切换规则也不容易更改。

了解了这些限制你才会明白为什么需要在用户态又搞个协程。

协程又称为轻量级线程,它也有轻量栈、状态、调度器(类似一个管理CPU分配的内核)。它相比于线程(内核管理,开销大、不灵活)、更加灵活轻量、CPU的分配完全由用户自定义。

(我会在后续博文详细介绍协程给大家,包括协程的优点、理念、以及协程库的实现和妙用!!!!)

http://www.dtcms.com/a/512731.html

相关文章:

  • 网站布局案例网站内容如何管理
  • (持续更新中!!~)30、原来可以这样理解C语言_项⽬实践-贪吃蛇
  • 信息展示网站余姚企业网站建设公司
  • YOLOv4 核心技术解析与优势
  • 深入理解STL关联容器:map/multimap与set/multiset全解析
  • 【Linux应用开发·入门指南】详解文件IO以及文件描述符的使用
  • 山西建设执业注册中心网站查网站跳出率
  • 成都美誉网站设计网站建设英语词汇
  • spark组件-spark core(批处理)-rdd行动算子(action)
  • MOTR: End-to-End Multiple-Object Tracking with TRansformer推理学习
  • RedHat自动化Ansible的部署
  • 服务器iis做网站网站开发与设计实训心得一千字
  • 买域名后怎么做网站做门户网站需要多少钱
  • 海南网站建设网站开发小程序app网站建设培训相关资料
  • 供热设施网站搭建教程支付招聘网站套餐费用怎么做帐
  • 硬件 - 电量计配置GG详解 - 以BQ40Z80为例
  • 做公司网站优劣势阿里云建立wordpress
  • 中国电信收购腾讯东莞网络优化服务商
  • C++ 学习 —— 02 - 排序算法
  • 电商是干嘛的北京终端区优化
  • 高并发webserver_interview
  • 网站建设所需的基本条件wordpress汉化客户端
  • K8s 核心三组件:kubelet、kubeadm、kubectl 知识点梳理​
  • 网站设计的目的和意义seo是什么意思教程
  • 超低延迟与高并发:视频直播点播平台EasyDSS在游戏直播场景的技术实践
  • AIDD - 前沿生物科技 虚拟细胞 (Virtual Cells) 的头部公司
  • 做网站能带来什么问题数字创意设计包括哪些案例
  • 网络练习(选择题)
  • [环境配置]C4D OC渲染器解决缺少cudnn_9_7_0Octance正版缺少cudnn_9_7_0_win文件解决方法
  • 文档流程做网站深圳营销网站建设报价