2026/4/18 6:29:19
网站建设
项目流程
淄博网站seo公司,厦门中标工程信息网,seo快速优化软件,黄骅市旅游景点有哪些目录 最直白的讲解几者关系
上下文切换
进程跟线程之间的关系
核心结论先敲定#xff1a;
为什么要有进程#xff1f;既然线程才干活#xff0c;直接用线程不行吗#xff1f; 最直白的讲解几者关系
我们把操作系统比作一个公司 一个个进程比作部门 线程就是部门的成员…目录最直白的讲解几者关系上下文切换进程跟线程之间的关系核心结论先敲定为什么要有进程既然线程才干活直接用线程不行吗最直白的讲解几者关系我们把操作系统比作一个公司 一个个进程比作部门 线程就是部门的成员而成员一会要干a任务一会要干b任务 工作的流程方式叫做协程。io密集型就是成员线程不忙但是一直在等 要么考虑加协程(工作流要么考虑加成员线程cpu密集型就是成员线程已经忙不过来了 要么考虑加成员共享数据频繁 要么考虑加部门(追求任务隔离性)上下文切换上下文切换开销本质上就是不同任务进程 / 线程 / 协程之间切换执行时产生的系统开销但不同类型任务的切换开销来源、量级差异极大这也是协程在高并发场景下性能优势的核心原因。下面从技术本质、开销构成、不同任务类型的对比三个维度帮你把这个概念讲透。一、上下文切换的本质操作系统的 CPU 核心同一时间只能执行一个任务进程 / 线程当需要切换到另一个任务时必须先保存当前任务的执行状态再恢复目标任务的执行状态这个过程就是上下文切换而保存和恢复状态的所有消耗就是上下文开销。你可以把它类比成员工 A 正在做报表突然要切换去做 PPT需要先把报表的当前进度、打开的文件、思路都记下来保存上下文然后打开 PPT 软件、找到对应的项目文件、回忆之前的设计思路恢复上下文这个过程消耗的时间和精力就是 “切换开销”。二、上下文开销的具体构成上下文切换的开销主要分为两类内核态切换的开销远大于用户态内核态上下文切换开销进程 / 线程寄存器保存与恢复CPU 的通用寄存器、程序计数器PC、栈指针等核心执行状态需要保存到内核栈再加载新任务的寄存器状态。内核数据结构更新操作系统需要更新任务的状态如从运行态变为就绪态、调度队列、内存管理信息如页表等。缓存失效CPU 的 L1/L2/L3 缓存、TLB地址转换缓存是针对当前任务的切换后缓存命中率大幅下降需要重新加载数据这是开销最大的部分之一。系统调用开销切换过程需要从用户态进入内核态再回到用户态这个模式切换本身就有固定开销。用户态上下文切换开销协程仅需要保存和恢复协程的用户态寄存器如栈指针、程序计数器无需涉及内核数据结构。协程的栈通常很小几 KB 到几十 KB切换时无需刷新 CPU 缓存和 TLB缓存命中率几乎不受影响。完全在用户态完成不需要进入内核没有系统调用的开销。三、进程、线程、协程的上下文开销对比任务类型切换触发者开销量级主要开销来源适用场景进程切换操作系统内核最大几十到几百纳秒页表切换、缓存失效、内核数据结构更新任务完全隔离、稳定性要求高的场景线程切换操作系统内核中等几到几十纳秒寄存器保存恢复、缓存局部性下降CPU 密集型任务并行、需要共享资源的场景协程切换用户态程序极小几纳秒以下仅用户态寄存器保存恢复高并发 IO 密集型场景如百万级连接的服务器四、为什么上下文开销对性能影响巨大在高并发场景下频繁的上下文切换会导致 CPU 的大量时间浪费在 “保存 / 恢复状态” 上而不是真正执行业务逻辑比如一个高并发 Web 服务器如果用多线程处理 10 万个连接线程切换开销会占 CPU 的 50% 以上导致业务处理能力大幅下降。而用协程处理同样的连接切换开销几乎可以忽略CPU 能全力处理业务性能可提升数倍甚至数十倍。五、C 中的实际体现线程切换当你用std::thread创建多个线程操作系统会负责调度当线程数超过 CPU 核心数时就会频繁发生上下文切换你可以通过top命令Linux看到%sys内核态 CPU 占用升高这就是切换开销的体现。协程切换C20 协程的切换完全由程序控制比如用co_await让出执行权时仅保存协程的栈帧和寄存器状态开销极小适合实现高并发的 IO 服务。进程跟线程之间的关系核心结论先敲定进程本身从不干活它只是一个「资源容器 / 任务外壳」真正执行代码、完成具体工作的只有线程线程是进程的「执行单元」进程必须依赖线程才能运行抛开线程进程就是一个空架子啥也做不了一、再用类比把「进程不干活、线程干所有活」讲死公司 操作系统部门 进程→ 部门本身不产出、不干活部门的作用是「申请 持有」公司的资源比如办公室、电脑、打印机、项目预算、客户资料。部门里的员工 线程→员工才是真正干活的人员工拿着部门的资源用电脑、查资料、用打印机完成具体的工作写代码、做报表、谈客户。核心对应进程部门只占有资源不执行任务线程员工使用进程的资源执行具体任务没有员工的部门无线程的进程空有资源完全闲置啥活干不了员工必须隶属于某个部门线程必须属于某个进程不可能存在脱离部门的员工也不存在脱离进程的线程。二、从技术层面讲清「进程的本质是容器线程的本质是执行者」进程的核心使命「占资源」仅此而已操作系统创建一个进程本质上是为它分配一套独立的专属资源这些资源是线程干活的「基础保障」进程的所有资源会被自己内部的所有线程共享进程的核心工作只有 2 个向操作系统申请资源独立的内存空间、文件句柄、网络端口、系统权限等持有并管理这些资源保证资源只给自己的线程用进程退出时统一释放所有资源。进程从头到尾不会执行任何一行业务代码它的存在只是为线程「搭好舞台」。线程的核心使命「执行代码」干完所有活线程是操作系统中最小的执行单元它没有自己的独立资源几乎 0 资源但它可以直接使用所属进程的全部资源。CPU 在操作系统中调度的核心对象不是进程而是线程操作系统的 CPU 核心只会给线程分配执行时间让线程去跑代码线程拿到 CPU 时间片 → 执行程序里的一行行代码加减乘除、读写文件、网络请求线程干完自己的任务 → 要么等待下一次调度要么结束运行一个进程里可以有多个线程这些线程共享进程的资源协同完成一个复杂任务比如一个 APP 进程有「界面渲染线程」「网络请求线程」「数据存储线程」各司其职。三、必须掌握的关键细节「进程一创建就自带 1 个线程」你可能会疑惑我平时写个单线程程序只创建了进程没手动创建线程为啥程序能正常运行 这是操作系统的「默认规则」当你创建一个进程时操作系统会自动为这个进程创建「第一个线程」—— 主线程Main Thread举个最常见的例子你写一个 C/C/Java/Python 的简单程序编译运行后操作系统会生成一个进程同时自动创建主线程你的main()函数本质上就是主线程的入口代码是主线程在执行main()里的所有逻辑。你不手动创建线程 → 进程里只有「主线程」1 个执行者串行干活你手动创建线程 → 进程里有多个执行者并行干活哪怕你创建 100 个线程这些线程也都属于同一个进程共享进程的所有资源。四、进程 线程 最核心的 3 个关系总结1. 从属关系线程是进程的「子集」线程必须隶属于某一个进程一个进程可以包含1 个或多个线程主流系统中进程至少有 1 个线程反之不存在脱离进程的独立线程。2. 分工关系进程管「资源」线程管「执行」进程资源分配的基本单位→ 只拿资源、不干活线程程序执行的基本单位→ 只用资源、干所有活。3. 依赖关系进程的运行完全依赖线程进程的生命周期和线程绑定进程启动 → 主线程自动启动开始执行代码进程内所有线程都执行完毕→ 进程才会随之退出若进程被强制终止 → 它内部的所有线程会被「一刀切」全部销毁。为什么要有进程既然线程才干活直接用线程不行吗核心原因进程是为了「隔离资源」线程是为了「高效执行」。如果只有线程、没有进程所有线程共享操作系统的全局资源一个线程出错比如内存越界会直接导致整个操作系统崩溃安全性极差有了进程之后每个进程的资源是相互独立、相互隔离的A 进程里的线程出错只会导致 A 进程崩溃不会影响 B 进程、更不会影响操作系统稳定性和安全性直接拉满。一句话总结两者的存在意义进程负责「隔离风险、管理资源」线程负责「高效干活、执行任务」二者缺一不可协同工作。最终核心结论进程不干活只是「资源容器」线程是唯一的「执行者」干所有活线程属于进程进程依赖线程才能运行进程管资源线程管执行。