实际上,使用pthread_create 传递给线程函数的数据应该是静态数据(但是您只能使用它创建一个线程,因为它不是可重入的)或堆分配的数据,或者指针转换成别的东西。如果它是本地数据,它将在启动的线程完成之前被销毁(除非您采取特定的预防措施,例如在调用 pthread_create 的 same 函数中调用 pthread_join)。
这里有一些例子,假设一个全局的pthread_t thr;变量和下面的线程函数
void *run_thread(void*p) {
int* pi = p;
(*pi)++;
printf("in thread data=%d\n", *pi);
return pi;
}
一个带有静态数据的线程
回想一下,对于静态数据,您的代码是不可重入的,并且您只能有 一个 线程使用该数据。
void run_my_thread(void) {
static int x;
int err = pthread_create(&thr, NULL, run_thread, &x);
if (err)
{ fprintf(stderr, "pthread failed %d (%s)\n", err, strerror(err));
exit(EXIT_FAILURE);
}
do_something_else();
void* res = NULL;
pthread_join(thr, &res);
if (res) printf("got %d from thread\n", *(int*)res);
}
一个常见的模式可能是有一个静态数组,例如5 个数据元素,正好运行 5 个线程,每个线程处理该静态数组中自己的元素。
堆分配数据的线程
void run_my_thread(void) {
int *pi = malloc(sizeof(int));
if (!pi) {perror("malloc"); exit(EXIT_FAILURE); };
*pi = 42;
int err = pthread_create(&thr, NULL, run_thread, pi);
if (err)
{ fprintf(stderr, "pthread failed %d (%s)\n", err, strerror(err));
exit(EXIT_FAILURE);
}
do_something_else();
void* res = NULL;
pthread_join(thr, &res);
if (res) printf("got %d from thread\n", *(int*)res);
free (pi), pi = NULL;
}
有时,但这很丑陋,您可能会将转换后的inptr_t 值(不是指向它的指针)传递给pthread_create。
intptr_t 数据线程
当然,在线程例程中将其用作取消引用的指针是没有意义的,可能是:
void*run_thread_int(void*p) {
intptr_t i = (intptr_t)p;
printf("i=%d\n", i);
return NULL;
}
然后你就可以编码了
void run_my_thread_int(void) {
intptr_t j=53;
int err = pthread_create(&thr, NULL, run_thread_int, (void*)j);
if (err)
{ fprintf(stderr, "pthread failed %d (%s)\n", err, strerror(err));
exit(EXIT_FAILURE);
}
do_something_else();
pthread_join(thr, NULL);
}
考虑pthread_create 的一种实用方法是将线程函数视为在机器寄存器中获取单个参数,该寄存器可以保存一个指针(或intptr_t 上面的技巧)。
大多数时候你会使用一个堆分配struct(包装几个值)作为参数到你的线程函数。