如何将线程参数作为引用而不是值传递?

时间:2014-10-23 17:34:39

标签: pthreads pthread-join

#include <pthread.h> 
#include <stdio.h> 
#include <unistd.h> 
#include <stdlib.h>

const int kMaxThreads = 10;

void * threadRoutine(void * threadArg) {
    int myThreadNumber = * ((int * ) threadArg);
    //(int)threadArg
    printf("threadRoutine()=>: this is thread number %d!\n", myThreadNumber);
    int sleepTime = random() % 20;
    sleep(sleepTime);
    printf("threadRoutine()=>: thread[%d] completed after sleeping %d [secs]!\n",
        myThreadNumber, sleepTime);
    pthread_exit((void * ) myThreadNumber);
}

int main(int argc, char * argv[]) {
    pthread_t threads[kMaxThreads];
    printf("main()=>: creating threads...\n");
    for (int jj = 0; jj < kMaxThreads; jj++) {
        if (pthread_create( & threads[jj], NULL, threadRoutine, (void * ) jj) != 0) {
            /* undefined reference to a pthread_create*/
        } else {
            printf("main()=>: created thread[%d]!\n", jj);
        }
    }
    printf("main()=>: waiting for threads to complete...\n");
    for (int jk = 0; jk < kMaxThreads; jk++) {
        void * currentThread;
        if (pthread_join(threads[jk], & currentThread) != 0) {
            /* undefined reference to a pthread_join*/
        } else {
            printf("main()=>: completed thread[%d]!\n", (int) currentThread);
        }
    }
}

我遇到了麻烦,创建并加入了一个帖子。我也不确定如何通过引用传递线程参数的语法。代码应该在创建线程时打印,以及在线程例程中休眠多长时间。

2 个答案:

答案 0 :(得分:0)

您发布的代码使用pthread_create()允许您传递给线程函数的单个参数来执行“坏事”。 pthread_create()允许传递单个void *(通常可以通过从其他内容中转换来获得)。在你的情况下,你这样做:

pthread_create(..., (void * ) jj)

这将获取存储在jj中的整数值,将其重新解释为void *,并且此指针将传递给您的线程函数。严格来说,将int重新解释为void *充其量是可疑的,但这就是设计PThreads API的方式。

在你的线程函数中,你这样做:

int myThreadNumber = * ((int * ) threadArg);

这将获取您传递的void *,并将其重新解释为指向int(又名(int *))的指针,这在大多数平台上通常是可以接受的,但会导致在您的使用中,int *的值为01,...然后,您尝试取消引用此指针,以使用int获取* ((int *) ...)。在大多数现代系统中,循环的第一次迭代将因此导致空指针取消引用(尽管NULL指针不能保证数字值为0,但这些天通常会在大多数系统/编译器上执行),并且可能会导致结果导致程序崩溃,除非您正在捕捉并忽略相关信号等。

你应该在你的线程函数中做的是将void *强制转换回开始构建的。换句话说,int myThreadNumber = (int) threadArg。或者,你可以改为调用pthread_create(.... (void *) &jj),如果你真的想要一个指向int的指针,那么你可以传回信息 - 但这似乎不是你在这里想要做的,并且将指针传递给基于堆栈的局部变量在其他方面会是一件坏事。

我不确定您对通过引用与值传递参数的期望是什么。 API声明您必须传递void *,这就是您必须做的事情,除非您想请求PThreads人员更改API ...或者自己编写...

答案 1 :(得分:0)

你在做什么:

  pthread_create( & threads[jj], NULL, threadRoutine, (void * )jj) ;

int jj转换为void*,并将传递给threadRoutine()。这很合理。问题似乎是在threadRoutine()你:

  int myThreadNumber = * ((int * ) threadArg);

这就是我们所说的&#34;一个错误&#34;。应该做的是:

  int myThreadNumber = (int)threadArg ;

或可能:

  int myThreadNumber = (intptr_t)threadArg ;

void*指针强制转换回int

通过引用传递jj需要以下内容:

  int thread_arg[kMaxThreads] ;

  for (int jj = 0; jj < kMaxThreads; jj++) {
    thread_arg[jj] = jj ;
    if (pthread_create( & threads[jj], NULL, threadRoutine, &thread_arg[jj]) != 0) {
        /* undefined reference to a pthread_create*/
    } ...

然后你原来

  int myThreadNumber = * ((int * ) threadArg);

可以拿起价值。

当然,线程有权在它运行时随时使用threadArg指向的东西......所以你需要确保它在那么长时间内保持有效。在这种情况下,thread_arg[jj]仅由第jj个线程使用,并且一直存在,直到该线程已加入beem之后...所以一切都很好。