如何为0至n-1的pthreads线程分配序号?求无内存泄漏最优方案
问题描述
我需要创建n个编号为0到n-1的pthreads线程,直接传递循环变量i的地址无法正常工作:
#include <pthread.h> #include <stdio.h> #define MY_THREAD_COUNT 6 void *runner(void *param) { int id = *(int*)param; printf("Thread %d\n", id); } int main() { pthread_t thread_arr[MY_THREAD_COUNT]; for (int i = 0; i < MY_THREAD_COUNT; i++) pthread_create(&thread_arr[i], NULL, runner, &i); for (int i = 0; i < MY_THREAD_COUNT; i++) pthread_join(thread_arr[i], NULL); }
执行后输出序号混乱,例如:
Thread 2
Thread 2
Thread 3
Thread 4
Thread 5
Thread 6
为每个线程序号单独malloc内存的方案可以得到正确序号:
for (int i = 0; i < MY_THREAD_COUNT; i++) { int *tmp = malloc(sizeof(int)); *tmp = i; pthread_create(&thread_arr[i], NULL, runner, tmp); }
执行后输出例如:
Thread 0
Thread 1
Thread 2
Thread 4
Thread 5
Thread 3
但该方案会引发内存泄漏,并非理想选择。请问能否在runner函数内通过类似pthread_self的函数获取0到n-1的连续序号?或者更宽泛地说,实现该需求最简洁的方案是什么?
解决方案
关于pthread_self获取连续序号的问题
不行。pthread_self()返回的是pthread_t类型的线程标识,它是操作系统分配的线程唯一标识符,不保证是0到n-1的连续整数,也没有标准方法可以将其转换为我们需要的连续编号,所以无法通过这种方式获取目标序号。
最简洁的两种实现方案
方案1:利用数组存储独立序号
在主线程中创建一个数组,每个元素存储对应线程的序号,传递数组元素的地址给线程。这样每个线程拿到的是独立的内存地址,不会被主线程的循环变量修改:
#include <pthread.h> #include <stdio.h> #define MY_THREAD_COUNT 6 void *runner(void *param) { int id = *(int*)param; printf("Thread %d\n", id); return NULL; } int main() { pthread_t thread_arr[MY_THREAD_COUNT]; int thread_ids[MY_THREAD_COUNT]; // 存储每个线程的序号 for (int i = 0; i < MY_THREAD_COUNT; i++) { thread_ids[i] = i; pthread_create(&thread_arr[i], NULL, runner, &thread_ids[i]); } for (int i = 0; i < MY_THREAD_COUNT; i++) { pthread_join(thread_arr[i], NULL); } return 0; }
方案2:直接传递序号值(类型转换法)
利用C标准中的intptr_t类型(定义在<stdint.h>中),将整数序号转换为void*类型传递,在runner中再转换回来。这种方案不需要额外数组,代码更简洁:
#include <pthread.h> #include <stdio.h> #include <stdint.h> // 引入intptr_t的定义 #define MY_THREAD_COUNT 6 void *runner(void *param) { int id = (int)(intptr_t)param; // 转换回整数 printf("Thread %d\n", id); return NULL; } int main() { pthread_t thread_arr[MY_THREAD_COUNT]; for (int i = 0; i < MY_THREAD_COUNT; i++) { // 将i转换为void*类型传递 pthread_create(&thread_arr[i], NULL, runner, (void*)(intptr_t)i); } for (int i = 0; i < MY_THREAD_COUNT; i++) { pthread_join(thread_arr[i], NULL); } return 0; }
方案说明
- 原错误方案的问题:所有线程共享同一个循环变量
i的地址,主线程的循环会快速修改i的值,线程执行时读取的是i的当前值而非创建时的序号,导致输出混乱。 malloc方案的改进(可选):如果一定要用malloc,可以在runner函数末尾加上free(param);来避免内存泄漏,但相比上述两种方案,代码冗余度更高。
内容的提问来源于stack exchange,提问作者motaylormo
相关产品推荐
相关产品推荐

