C pthread_创建并传递一个整数作为最后一个参数

C pthread_创建并传递一个整数作为最后一个参数,c,pthreads,C,Pthreads,我有以下职能: void *foo(void *i) { int a = (int) i; } int main() { pthread_t thread; int i; pthread_create(&thread, 0, foo, (void *) i); } 在编译时,关于强制转换((void*)i和int a=(int)i)有一些错误。如何正确地传递整数作为pthread\u create的最后一个参数?您可以在堆上分配int,并将其传递给pt

我有以下职能:

void *foo(void *i) {
    int a = (int) i;
}

int main() {
    pthread_t thread;
    int i;
    pthread_create(&thread, 0, foo, (void *) i);
}

在编译时,关于强制转换(
(void*)i
int a=(int)i
)有一些错误。如何正确地传递整数作为
pthread\u create
的最后一个参数?

您可以在堆上分配
int
,并将其传递给
pthread\u create()
。然后,您可以在线程函数中取消分配它:

void *foo(void *i) {
    int a = *((int *) i);
    free(i);
}

int main() {
    pthread_t thread;
    int *i = malloc(sizeof(*i));
    pthread_create(&thread, 0, foo, (void *) i);
}

您应该在pthread_create()的最后一个参数中强制转换
i
的地址(而不是像现在这样转换
i
的值)

而且你的演技也是错误的。应该是:

int a = *((int*) i);
  • 如果要读取该值,还应在main()中将
    i
    初始化为某个值,因为它现在未初始化
  • 2对main()使用正确的定义:

    int main(int argc,char*argv[])
    或其等效项。

    基于szx的答案(因此请给他评分),以下是它在
    for
    循环中的工作方式:

    void *foo(void *i) {
        int a = *((int *) i);
        free(i);
    }
    
    int main() {
        pthread_t thread;
        for ( int i = 0; i < 10; ++1 ) {
            int *arg = malloc(sizeof(*arg));
            if ( arg == NULL ) {
                fprintf(stderr, "Couldn't allocate memory for thread arg.\n");
                exit(EXIT_FAILURE);
            }
    
            *arg = i;
            pthread_create(&thread, 0, foo, arg);
        }
    
        /*  Wait for threads, etc  */
    
        return 0;
    }
    
    void*foo(void*i){
    int a=*((int*)i);
    免费(i);
    }
    int main(){
    pthread\u t线程;
    对于(int i=0;i<10;++1){
    int*arg=malloc(sizeof(*arg));
    如果(arg==NULL){
    fprintf(stderr,“无法为线程arg分配内存。\n”);
    退出(退出失败);
    }
    *arg=i;
    pthread_创建(&thread,0,foo,arg);
    }
    /*等待线程等*/
    返回0;
    }
    

    在循环的每次迭代中,您都在分配新内存,每个内存都有不同的地址,因此在每次迭代中传递给
    pthread\u create()
    的内容是不同的,因此,没有一个线程会尝试访问相同的内存,并且不会像传递
    i
    的地址那样出现任何线程安全问题。在本例中,您还可以设置一个数组并传递元素的地址。

    这是一个老问题,但我今天遇到了同样的问题,我决定不走这条路。 我的应用程序实际上是关于性能的,所以我选择静态声明
    int
    s数组

    由于我不知道有多少应用程序的
    pthread\u join
    /
    pthread\u cancel
    位于
    pthread\u create
    之外的另一个范围内,因此我选择了以下方式:

    #define NB_THREADS 4
    
    void *job(void *_i) {
      unsigned int i = *((unsigned int *) _i);
    }
    
    int main () {
      unsigned int ints[NB_THREADS];
      pthread_t    threads[NB_THREADS];
      for (unsigned int i = 0; i < NB_THREADS; ++i) {
        ints[i] = i;
        pthread_create(&threads[i], NULL, job, &ints[i]);
      }
    }
    
    #定义NBU线程4
    void*作业(void*\u i){
    无符号整数i=*((无符号整数*)\u i);
    }
    int main(){
    无符号整数[NB_线程];
    pthread_t threads[NB_threads];
    for(无符号整数i=0;i

    我发现它更优雅、更高效,而且您不必担心释放,因为它只存在于此范围内。

    虽然这是一个老问题,但当您只需要像描述符一样传递正整数时,缺少一个选项:您可以直接将其作为地址传递,虽然它是一个黑客,但它工作良好,避免分配任何东西:)

    注意:整数的大小必须与操作系统上指针的大小相匹配,但现在大多数系统都是64位本机系统

    #include <pthread.h>
    #include <inttypes.h>
    #include <stdio.h>
    
    void *_thread_loop(void *p)
    {
      uint64_t n = (uint64_t)p;
    
      printf("received %llu\n", n);
    
      return NULL;
    }
    
    
    
    int main(int argc, char const *argv[])
    {
      pthread_t read_thread_id;
      uint64_t n = 42;
      pthread_create(&read_thread_id, NULL, _thread_loop, (void *)n);
    
      pthread_join(read_thread_id, NULL);
      return 0;
    }
    
    #包括
    #包括
    #包括
    void*\u线程\u循环(void*p)
    {
    uint64_t n=(uint64_t)p;
    printf(“收到%llu\n”,n);
    返回NULL;
    }
    int main(int argc,char const*argv[]
    {
    pthread_t read_thread_id;
    uint64_t n=42;
    pthread_create(&read_thread_id,NULL,_thread_loop,(void*)n);
    pthread_join(read_thread_id,NULL);
    返回0;
    }
    
    如果在
    for
    循环中声明了
    i
    ,这是否有效?例如,
    For(inti=0;…)
    或者我应该在
    For
    循环之前声明它吗?在For循环中声明也一样&它的工作方式是相同的。但只有在C99(或更高版本)模式下才允许在for循环中声明变量。例如,您需要使用
    -std=c99
    以及其他编译器选项进行编译。此外,如果我使用
    &I
    ,那么我将为线程提供变量
    I
    的地址。如果我创建了其他线程,
    I
    不会在所有线程之间共享吗?这不是我们想要的行为。我不确定第二种解决方案是否有效。当第一个线程到达
    inta=*((int*)i)
    时,for循环可能已经更改了
    i
    的值。因此,当第一个线程尝试初始化
    a
    时,它将无法读取正确的值。@Gradient:您是正确的,传递循环变量的地址不能保证安全。将
    int
    强制转换为指针并返回的结果由实现定义,因此这也不是一个很好的解决方案。使用
    malloc()
    是最好的方法。正如我在另一个答案中所说:我不确定这个解决方案是否有效。当第一个线程到达
    inta=*((int*)i)
    时,for循环可能已经更改了
    i
    的值。因此,当第一个线程尝试初始化
    a
    时,它不会读取正确的值。或者我对线程的概念感到困惑?@Gradient:你的另一个评论是正确的,但这里并不是这样。此解决方案为每个线程分配参数的新内存(或者,至少,如果将其放入循环中,则会在每个循环中分配新内存),因此每个线程都会获得一个不同的对象,并且没有两个线程尝试访问同一内存。你对线程的概念理解正确,这个解决方案没有表现出你提到的问题。我认为,通过实际展示它在循环中的工作方式,这个解决方案将会得到改进。我在编译时得到了这一点:
    error:invalid conversion from'void*'to'int*'
    在这一行:
    int*arg=malloc(sizeof(*arg))。你应该在MaloC之前放置(int *)。@渐变:你必须编译为C++。在C语言中,强制转换是不必要的,在我看来,不应该包括在内应改为
    int*arg=
    
    #define NB_THREADS 4
    
    void *job(void *_i) {
      unsigned int i = *((unsigned int *) _i);
    }
    
    int main () {
      unsigned int ints[NB_THREADS];
      pthread_t    threads[NB_THREADS];
      for (unsigned int i = 0; i < NB_THREADS; ++i) {
        ints[i] = i;
        pthread_create(&threads[i], NULL, job, &ints[i]);
      }
    }
    
    #include <pthread.h>
    #include <inttypes.h>
    #include <stdio.h>
    
    void *_thread_loop(void *p)
    {
      uint64_t n = (uint64_t)p;
    
      printf("received %llu\n", n);
    
      return NULL;
    }
    
    
    
    int main(int argc, char const *argv[])
    {
      pthread_t read_thread_id;
      uint64_t n = 42;
      pthread_create(&read_thread_id, NULL, _thread_loop, (void *)n);
    
      pthread_join(read_thread_id, NULL);
      return 0;
    }