问题

操作系统多进程多线程的相关问题?

回答
操作系统里的多进程和多线程,这俩玩意儿可以说是让程序跑得飞起、效率倍增的“幕后推手”。不过,它们俩可不是一回事儿,各自有自己的玩法和优缺点。咱这就掰开了揉碎了说,保证你说得明明白白。

先说说多进程,这就像是咱家里好几个独立的家庭,各自过着各自的日子。

想象一下,你开了一台电脑,同时运行着浏览器、音乐播放器、聊天软件,甚至可能还有一个虚拟机。这些你看到的、能操作的,绝大多数都是一个一个独立的“进程”。每个进程都像是电脑里的一个“小王国”,有自己的地盘(内存空间)、自己的资源(CPU时间、文件句柄等),还有一套自己的“规矩”(进程ID、进程状态等)。

核心特点是啥?独立!

独立的内存空间: 这是最重要的。每个进程都有自己私有的内存区域,就像每个家庭都有自己独立的房子。一个进程里的数据,另一个进程根本就看不到、也碰不到。这带来了极大的安全性——一个进程崩溃了,比如浏览器卡死了,一般不会影响到其他正在运行的程序,比如你的音乐播放器依然会好好播放。这种隔离性让系统更稳定。
独立的资源: 每个进程都需要 CPU 时间来执行指令,也可能需要访问磁盘、网络等资源。操作系统会负责给每个进程分配这些资源,并且要保证公平分配。
通信相对复杂: 正因为内存空间是隔离的,进程之间想“说话”,那就得通过一些特殊的“信道”,比如管道(pipe)、消息队列(message queue)、共享内存(shared memory)或者套接字(socket)等等。这就像两个家庭想交流,得通过电话、邮件或者派个信使过去,过程会相对麻烦一些。
创建和切换成本高: 创建一个进程需要操作系统分配一大堆东西:独立的内存空间、各种控制信息、文件句柄等等。这个过程就像是建立一个新的家庭,从头开始准备各种东西,所以开销挺大的。同样,操作系统在不同进程之间切换执行权时,也需要保存和恢复很多状态信息,这个切换过程也比在同一个进程内部切换要慢一些。

啥时候会用到多进程呢?

安全性要求高: 比如你运行一个网络服务,为了防止一个恶意请求导致整个服务器瘫痪,你可以把每个客户端连接都放到一个独立的进程里处理。这样,即使某个进程被搞挂了,也不会影响到其他服务。
需要充分利用多核CPU: 如果你的任务可以拆分成多个完全独立的子任务,并且这些子任务之间没有太多依赖,那么用多个进程并行执行,就能充分利用多核CPU的威力,大大缩短总执行时间。
简单任务的并行: 比如你有很多文件需要处理,每个文件处理过程互相独立,就可以起多个进程来同时处理这些文件。

接下来,咱们聊聊多线程。这就像是一个大家庭里,有好几个兄弟姐妹,一起在家里活动。

线程,是进程内部更小的执行单元。一个进程可以包含一个或多个线程。你可以把进程想象成一个“工厂”,而线程就是这个工厂里的“工人”。

核心特点是啥?共享!

共享进程的资源: 这是线程最牛的地方。同一进程内的所有线程,都共享这个进程的地址空间(内存),包括代码段、数据段、堆等。这意味着,线程之间可以直接访问和修改同一份数据,就像一个家庭里的成员可以直接拿到冰箱里的食物一样。
通信效率高: 因为共享内存,线程之间的通信非常方便,可以直接读写共享变量。就像家里人之间直接对话一样,效率极高。
创建和切换成本低: 创建一个线程,相比创建一个进程,只是在进程的基础上多了一个执行流,开销小得多。线程的切换也只需要保存和恢复少量的CPU寄存器和栈信息,比进程切换要快很多。
容易出现数据竞争: 由于共享数据,如果多个线程同时修改同一块数据,就可能出现“乱序”或者不一致的情况,这就是所谓的“数据竞争”(Data Race)。比如两个线程同时给一个账户加钱,如果操作顺序不对,可能会导致加钱失败或者重复。这就需要用到锁(Lock)、信号量(Semaphore)等同步机制来保护共享数据。
一个线程崩溃可能导致整个进程崩溃: 由于线程共享进程资源,如果一个线程出了严重错误(比如访问了非法内存),很可能就会导致整个进程崩溃,就像家里一个人突然生重病,可能会影响到所有家庭成员的正常生活。

啥时候会用到多线程呢?

提高程序的响应速度: 比如一个GUI应用程序,当你点击一个按钮进行一个耗时操作时,如果这个操作在一个单独的线程里执行,那么主线程(负责处理用户界面事件)仍然可以响应其他用户操作,不会出现界面卡死的情况。
并发执行任务: 很多时候,程序需要同时处理多个事情。比如一个Web服务器,可以为每个客户端请求创建一个线程来处理,这样就能同时服务多个用户。
利用多核CPU: 和多进程一样,多线程也可以利用多核CPU来并行执行。而且由于线程切换和创建成本低,对于那些需要频繁切换任务或者任务之间联系比较紧密的场景,多线程可能更合适。

总结一下,这俩好兄弟的区别就像是独立家庭 vs. 同一个大家庭里的成员:

| 特性 | 多进程 | 多线程 |
| : | : | : |
| 内存空间 | 各自独立,互不干扰 | 共享所属进程的内存空间 |
| 资源 | 各自拥有独立的资源(文件句柄等) | 共享所属进程的资源 |
| 通信 | 复杂,需要IPC机制(管道、消息队列等) | 简单高效,直接访问共享内存 |
| 创建/切换| 开销大 | 开销小 |
| 稳定性 | 一个进程崩溃不影响其他进程 | 一个线程崩溃可能导致整个进程崩溃 |
| 数据安全 | 隔离性好,不易出现数据竞争 | 易出现数据竞争,需同步机制 |
| 适用场景 | 进程隔离需求高、需要独立进程管理;充分利用多核执行独立任务 | 提高程序响应性、频繁I/O操作、任务间通信频繁 |

举个例子:

浏览器多进程: 你打开 Chrome 浏览器,通常情况下,每个标签页、每个插件、甚至浏览器本身的渲染进程、GPU进程都是独立的进程。这样,如果一个标签页卡住了,或者一个插件出了问题,只会影响那个特定的进程,不会导致整个浏览器崩溃。这就是多进程带来的隔离性和稳定性。
Word 文档多线程: 当你在 Word 里打字时,输入文字、格式化文本、拼写检查可能都在后台进行。你可以一边打字(一个线程),一边让 Word 自动保存(另一个线程),同时还在进行拼写检查(再一个线程)。这些操作都发生在同一个 Word 进程里,并且共享 Word 文档的数据。这就是多线程带来的并发性和响应性。

什么时候纠结用哪个?

这个问题其实没有标准答案,得看具体需求。

如果你需要非常高的隔离性,确保一个进程的失败不会影响到其他进程,并且任务之间关联性不强,那么多进程是更好的选择。 比如一些服务器程序,或者需要运行一些可能不稳定但独立的模块。
如果你的任务之间需要频繁地共享数据,并且对通信效率有较高要求,同时创建和切换的成本也需要考虑,那么多线程会是更优的方案。 比如一个图形界面应用,需要同时处理用户交互和后台数据加载。

一点小提示:

在很多现代操作系统和编程语言中,开发者还可以选择更轻量级的“协程”或“任务”(Coroutines/Tasks),它们比线程更灵活,切换成本更低,并且通常是在用户空间实现的,可以进一步提高并发能力,尤其是在处理大量I/O密集型任务时。不过,协程在底层还是需要线程来支撑的。

总而言之,多进程和多线程都是让程序变得更强大、更高效的重要手段。理解它们的原理、优缺点,才能在实际开发中做出更明智的选择,写出既稳定又高效的代码。

网友意见

user avatar

1.大多数调度器是按照线程调度的,而且,是的,你的线程越多你抢到的cpu也会越多,不过大多数情况下cpu是不用抢的,而计算密集的程序因为时刻处于就绪态也会比io密集的程序获得多得多的时间片,虽然通常计算密集程序的优先级更低

2.不过切个cr3没那么慢吧,而且触发各种中断的时候也可能切cr3,所以感觉对性能没多大影响……tlb不命中的开销确实是有一些的,不过切换线程也可能触发tlb不命中

3.调度肯定最终是调度到线程的,因为只有线程才有rip的值,没有rip就没办法iret。通常内存中会保存所有进程控制块和线程控制块,因通常os是不允许自己的内存被swap的,会大幅度降低效率,页表可以被换出。

每个核心的的调度过程其实可以说是独立的,每个核心的时钟中断是独立的,然后在触发调度时调度程序会在触发调度的那一个核心上进行,所以基本上调度器不需要考虑其他核心的调度情况,然后,因为每个核心都有自己的cr3寄存器,所以,任意4个线程,cpu不在乎是否来自同一个进程,一般调度器也不在乎

4.没必要,切cr3没多少时间,tlb缓存吧反正中断和系统调用都有可能tlb不命中呢,os只能把自己常用的东西放到tlb里面,不可能全放。再说现在内存这么大,tlb不命中还有内存呢,到需要访问swap中的页表的时候就是相对比较少的情况了。

5.异步时钟可以,cpu一个核心有几个可编程时钟,定时的长度可以调的。

6.大多数情况核心是互相独立的,中断,系统调用这些东西都是独立进行,cpu 0上可以运行控制其他核心的特权指令

7.没啥大区别,ipc是在内存中进行的,多核需要一些特殊的lock技巧什么的

user avatar
1.对于单核CPU,多线程程序和多进程程序调度是一样的吗?即例如最开始系统中有50个进程,加进来一个进程,每个进程的调度频率是1/51,再加进来一个进程,每个进程调度频率是1/52,所以对于一个多进程的程序,如果最开始它开启了2个进程,那么它的调度频率就是2/52。那么如果这个程序是一个进程中开启的是两个线程,那么它的调度周期是2/52,还是1/51,即操作系统是以线程调度还是进程调度。同时对于一个程序是不是开的进程或线程越多,那么一般情况下(不考虑进程线程创建,和特殊情况),这个程序的效率就越高(同一个调度周期内,它能够上CPU的机会更多)

绝大多数操作系统调度单位是线程,不是进程。

但跟你想象的不同,绝大多数的情况下CPU是闲着的而不是满着,你自己看任务管理器就知道了,在有些OS上时间片的长度不一定固定,如果真是计算密集型任务(需要吃CPU),操作系统会让它多占一会的。

2.对于问题1,如果是以线程为调度单位,那么操作系统会不会优化让连续一个进程的多个线程依次调度,这样就可以节省进程上下文的时间。

对于x86的CPU来说,切进程无非是换页+刷TLB这些,动作其实很快。你打开Windows任务管理器,看上去似乎很多进程,但多数进程都是闲着不干活的。

任务都是有一定优先级的,操作系统考虑的是根据优先级来调度,而不是切换上下文的时间,切换上下文的这点时间不算什么时间。

3.对于多核的CPU(例如4核),是以进程为调度单位,还是以线程为调度单位?如果以进程为调度单位,那么是不是内存中要同时保持4个进程的上下文?如果是以线程为单位,那么是否必须是同一个进程的4个线程,还是可以是4个不同进程的4个不同线程?

不管单核多核,调度单位都是线程,跟进程没关系。具体每个核是同一个进程还是不同进程,操作系统不关系,CPU也不关心,每个CPU都有寄存器能保存当前任务状态,其余的状态都在内存里。

4. 对于3的情况,如果是以线程为调度单位,操作系统是否可以优化,让一个进程的多个线程首先占据4个核,然后下一个调度周期优先让这个进程的其余线程继续跑,余下来的核再给其他进程的线程用,这样可以节省进程上下文的时间。

前面说了,进程切换的代价很低,而且多数情况下一个线程不可能跑满一个时间片,如果一个进程把全部核都占满,如果某些线程跑完了需要释放时间片怎么办?怎么解决每个线程占用时间片长度不同问题?

现场跑完了不释放CPU?浪费。

释放?又不符合你的模型,调度单位又变成线程了。

所以进程不作为调度的单位看待。

5. 多核CPU的每个核能否做到异步时钟?

可以。

6. 多个核,每个核操作系统是统一管理还是分别管理,总感觉对于每个进程在单核CPU中和多核CPU中的管理不同,正所谓4个核 != 一个核*4(效率方面)?

基于线程的调度效率比基于进程的效率高,因为一个进程的各个线程占用时间片是不同的,基于进程的调度会造成极大的CPU时间浪费。

7. 多个核,对于进程通信与线程同步有什么影响?

多核对于操作系统调度、锁的写法方面比较麻烦,对于上层应用,不需要考虑这些问题。按正常多线程加保护就够用了。

-------------------------------------

你的问题里,觉得任务切换的开销很大,实际上任务切换代价再大,也比浪费一个时间片要小

基于进程的多核调度,就意味着某些情况下,某些核的时间片被浪费掉,这种性能损失比任务切换要大得多。

一个时间片内做几百次任务切换都没问题,与其减少任务切换,不如把浪费的时间片都用上。

任务切换的代价比中断切换的代价要小,操作系统中各种外设的中断(时钟、PCI、DMA等)比任务切换的代价要大的多。

类似的话题

本站所有内容均为互联网搜索引擎提供的公开搜索信息,本站不存储任何数据与内容,任何内容与数据均与本站无关,如有需要请联系相关搜索引擎包括但不限于百度google,bing,sogou

© 2025 tinynews.org All Rights Reserved. 百科问答小站 版权所有