如何确定合适的线程数

Posted by KalosAner on March 22, 2025

一、引言

在多线程编程中,线程的数量会影响并发的性能。

过多的线程会消耗更多的资源,包括:

内存:pthread_create 创建出来的线程每个线程需要传递一个函数,所以每个线程都需要分配一个栈空间,占 8192 bytesulimit -a:查询栈空间大小)。std::thread 每个线程占用的空间可能较小。

切换:线程切换上下文会消耗 CPU 和时间。

并且大量唤醒的线程会增加系统负载。

32 位系统下每个进程的用户空间有 3G,所以一个进程最多创建 3G/8192 bytes ≈ 380 左右个线程。

二、任务类型

线程的任务类型可以大致分为两种,一种是 IO 密集型,一种是 CPU 密集型。

IO 密集型就是线程中有大量的 IO 操作,IO 操作会阻塞线程,使得 CPU 空闲下来,这样 CPU 的利用率就会降低。

CPU 密集型就是线程中的任务大多都需要 CPU 进行,很少进行阻塞,CPU 的利用率更高。

线程运行的环境也有所不同,有的线程需要运行在单核 CPU 上,有的线程需要运行在多核 CPU 上。对于单核 CPU 上的线程,多个线程同时运行的话称之为并发,也就是一种串行。对于多核 CPU 的线程,每个 CPU 的核都可以平行的运行一个线程,这种称之为并行。

三、线程状态

可用的线程一般有三个状态:调度中、就绪、阻塞。为了节省资源,CPU 不需要调度阻塞的线程,所以在内核中会使用两个队列来维护线程:

运行队列:存放就绪的或者正在调度的线程;

等待队列:存放阻塞的进程,当进程不在阻塞的时候再添加到运行序列。

在调度时,CPU 只会从运行队列选择需要执行的线程。

四、合适的数量

对于 IO 密集型的程序,等待队列中的线程比例相对较高,比较适合多线程。

对于 CUP 密集型的程序,单核 CPU 的话没有太大的必要使用多线程,多核 CPU 时可以使用 CPU 核数相等数量的线程。