创建8个绑定核心的线程后,为何出现更高编号的线程?
线程绑定后出现未预期线程编号的问题
我在32核Intel云实例上运行程序,希望仅使用8个线程,通过以下C代码创建并绑定线程:
#define _GNU_SOURCE #include <stdio.h> #include <pthread.h> #include <unistd.h> extern void * Complex_Calc_YZ_fn(); int thread_create_in_C(int numberOfProcessors) { pthread_t threads[numberOfProcessors]; pthread_attr_t attr; cpu_set_t cpus; pthread_attr_init(&attr); for (int i = 0; i < numberOfProcessors; i++) { CPU_ZERO(&cpus); CPU_SET(i, &cpus); printf("Core created %d\n", i); pthread_attr_setaffinity_np(&attr, sizeof(cpu_set_t), &cpus); pthread_create(&threads[i], &attr, Complex_Calc_YZ_fn, NULL); } for (int i = 0; i < numberOfProcessors; i++) { pthread_join(threads[i], NULL); printf("Core joined %d\n", i); } return numberOfProcessors; }
这段代码被链接到一个更大的程序中,且是程序中唯一创建和调度线程的逻辑。输出显示确实创建了8个线程,每个线程都通过pthread_attr_setaffinity_np绑定到对应核心。但在调试时,断点触发时却看到“thread 9”或“thread 10”的标识,而我只创建了编号0-7的8个线程。
我有两个问题:
- 当处理器有更多可用核心时,绑定到核心的线程编号是否会迁移?比如thread6会不会变成thread10?如果会,如何避免?
- 如果不会,还有哪些原因能解释这个现象?
问题解答
1. 绑定核心的线程编号是否会迁移?
不会。线程的pthread_t标识是进程内的唯一标识符,和CPU核心绑定逻辑完全无关。pthread_attr_setaffinity_np只是限制线程可以运行的CPU核心集合,并不会修改线程本身的ID,也不会导致线程编号“迁移”。你创建的线程ID会一直保持创建时的数值,不会因为CPU资源情况变化而改变。
2. 出现未预期线程编号的可能原因
- 主线程被计入总数:你创建的8个线程是额外线程,加上程序启动时就存在的主线程,进程内总共至少有9个线程。调试器显示的“thread 9”很可能就是主线程。
- 依赖库创建了后台线程:很多基础库或第三方组件会在后台隐性创建线程,比如:
- C标准库的内存分配器(如glibc的
malloc)可能会创建后台线程用于内存管理; - 日志、监控、信号处理组件;
- 动态链接库初始化时启动的线程;
这些线程不在你的代码控制范围内,但会被调试器检测到。
- C标准库的内存分配器(如glibc的
- 调试器的编号规则差异:调试器显示的“thread N”编号通常是调试器自身按线程发现顺序分配的序号,和线程实际的
pthread_t数值没有对应关系。比如主线程可能被编号为1,你创建的8个线程是2-9,若有额外后台线程就会被编为10及以上。 - 隐性线程创建逻辑:即使你认为自己的代码是唯一创建线程的地方,也可能存在遗漏——比如程序中其他模块调用了
pthread_create、fork(虽然fork是进程,但也可能关联线程),或者使用了线程池等组件,这些都可能产生额外线程。
内容的提问来源于stack exchange,提问作者RTC222
相关产品推荐
相关产品推荐

