CPU核数跟多线程的关系

一直以来有这样的疑惑,单核CPU适合多线程吗?是不是几个核的CPU开几个线程是最合适的?

今天就这一问题查了一些资料,现整理如下:

    要说多线程就离不开进程,进程和线程的区别在这里就不详细说了,只将关键的几点:

a)进程之间是相互独立的,不共享内存和数据,线程之间的内存和数据是公用的,每个线程只有自己的一组CPU指令、寄存器和堆栈,对于线程来说只有CPU里的东西是自己独享的,程序中的其他东西都是跟同一个进程里的其他线程共享的。

b)操作系统创建进程时要分配好多外部资源,所以开销大。(这个跟操作系统有关,有人做过实验,window创建进程的开销大,linux创建进程的开销就很小。)

    再来说一下CPU,在过去单CPU时代,单任务在一个时间点只能执行单一程序。之后发展到多任务阶段,计算机能在同一时间点并行执行多任务或多进程。虽然并不是真正意义上的“同一时间点”,而是多个任务或进程共享一个CPU,并交由操作系统来完成多任务间对CPU的运行切换,以使得每个任务都有机会获得一定的时间片运行。而现在多核CPU的情况下,同一时间点可以执行多个任务,具体到这个任务在CPU哪个核上运行,这个就跟操作系统和CPU本身的设计相关了。

    我们假设一个极端的情况:在一台单核计算机上只运行2个程序,一个是我们的程序A,另一个是操作系统的程序B,每个程序是一个进程。单核CPU的时候,A和B在CPU上交替运行,具体的分配方式由操作系统来判断,我这里猜测应该跟A和B的线程数有关,因为线程是CPU级别的,如果A有5个线程,B也有5个线程,那么CPU分配给A和B的时间应该是1:1的;如果A增加到15个线程,CPU分配给A和B的时间应该是3:1的比例。所以此时如果A的线程数多,那么获得的CPU执行次数就多,处理的速度也就快了。以上假设的前提是:①A和B的优先级相同,②A和B都是只消耗CPU资源的程序。

如果相同的情况用一个双核的计算机来处理又会是什么结果呢?假设这个双核的计算机和操作系统比较傻,把A进程分配到核1上,B进程分配到核2上,那不管A有几个线程,都是用核1来处理,那么时间肯定是一样的。不过现实中应该不会有这么傻的CPU和操作系统吧。偷笑所以赶紧还是会根据线程来进行处理,当A的线程比B多时,会占用核2来处理A的线程。

    刚才说的是只消耗CPU资源的程序,但这样的程序在实际应用中基本上是没有的,总会有跟资源打交道的。比如读个文件,查个数据库,访问一个网络连接等等。这个时候多线程才真正体现出优势,在一个进程中,线程a去读文件,线程b去查数据库,线程c去访问网络,a先用一下CPU,然后去读文件,此时CPU空闲,b就用一下,然后去查数据库,……,相对于读文件、查数据库、访问网络来说CPU计算的时间几乎可以忽略不计,所以多线程实际上是计算机多种资源的并行运用,跟CPU有几个核心是没什么关系的。






线程CPU 量之间的关系对程序性能有显著影响。理解这种关系有助于优化多线程程序的执行效率,尤其是在并发编程和资源调度中。 ### 线程CPU 心的关系 每个 CPU 心在某一时刻只能执行一个线程。这意味着在理想情况下,线程等于 CPU 时,所有心都能被充分利用。然而,实际情况并非如此简单。线程在执行过程中会遇到 I/O 操作、阻塞、等待资源等情况,这些阶段并不占用 CPU 资源。因此,如果线程等于 CPU ,那么在某些线程处于等待状态时,CPU 可能处于空闲状态,导致资源浪费。[^1] 现代 CPU 通常支持超线程技术(Hyper-Threading),即每个物理心可以模拟出两个逻辑心,从而同时执行两个线程。例如,一个四 CPU 支持超线程后可提供八个逻辑心,理论上可以同时运行八个线程。[^2] ### 不同任务类型对线程的影响 #### CPU 密集型任务 对于 CPU 密集型任务(如图像处理、科学计算等),线程的主要时间都用于计算,几乎不涉及 I/O 操作。在这种情况下,线程应设置为 CPU 的 1~2 倍。如果线程过多,会导致频繁的上下文切换,反而降低性能。[^3] #### I/O 密集型任务 对于 I/O 密集型任务(如文件读写、网络请求等),线程在执行过程中会频繁等待 I/O 操作完成。此时,线程不会占用 CPU 资源,因此可以设置更多的线程来填补 CPU 空闲时间。[^3] 《Java并发编程实战》中提出了一种计算线程的方法: ```java 线程 = CPU * (1 + 平均等待时间 / 平均工作时间) ``` 该公式表明,线程的等待时间越长,所需的线程就越多;反之,若工作时间较长(如 CPU 密集型任务),则线程应减少。[^3] ### 性能优化策略 为了充分发挥 CPU 性能,应根据任务类型合理设置线程池大小。对于 CPU 密集型任务,线程池大小应接近 CPU ;对于 I/O 密集型任务,线程池可以设置得更大,以提高并发能力。[^4] 此外,在 Linux 系统中,可以使用 `taskset` 或 `cpuset` 工具动态调整 CPU 心分配,从而优化多线程程序的性能。[^5] ### 示例:线程池配置(Java) ```java int corePoolSize = Runtime.getRuntime().availableProcessors() * 2; ExecutorService executor = Executors.newFixedThreadPool(corePoolSize); ``` 上述代码根据 CPU 设置线程池大小,适用于一般并发任务。 ---
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值