代码之家  ›  专栏  ›  技术社区  ›  Petr Peller

如何在C中从线程返回值

  •  43
  • Petr Peller  · 技术社区  · 14 年前

    我是C的新手,想玩点线。我想从线程返回一些值,使用 pthread_exit()

    我的代码如下:

    #include <pthread.h>
    #include <stdio.h>
    
    void *myThread()
    {
       int ret = 42;
       pthread_exit(&ret);
    }
    
    int main()
    {
       pthread_t tid;
       void *status;
    
       pthread_create(&tid, NULL, myThread, NULL);
       pthread_join(tid, &status);
    
       printf("%d\n",*(int*)status);   
    
       return 0;
    }
    

    我希望程序输出“42 \n”,但它输出一个随机数。如何打印返回值?

    编辑: 根据第一个答案,问题是我正在返回指向局部变量的指针。返回/存储多线程变量的最佳实践是什么?全局哈希表?

    提前谢谢

    8 回复  |  直到 9 年前
        1
  •  41
  •   anon    14 年前

    您返回的是一个局部变量的地址,当线程函数退出时,该变量不再存在。在任何情况下,为什么要调用pthread_exit?为什么不简单地从线程函数返回一个值呢?

    void *myThread()
    {
       return (void *) 42;
    }
    

    然后主要是:

    printf("%d\n",(int)status);   
    

    如果需要返回一个复杂的值(比如结构),那么通过malloc()动态分配它并返回一个指针可能是最容易的。当然,启动线程的代码将负责释放内存。

        2
  •  25
  •   Steve Jessop    14 年前

    您返回了一个指向局部变量的指针。即使不涉及线程,这也很糟糕。

    当启动的线程与连接的线程相同时,通常的方法是将指向int的指针传递给调用方管理的位置,作为pthread_create的第四个参数。然后,它将成为线程入口点的(唯一)参数。您可以(如果愿意)使用线程出口值指示成功:

    #include <pthread.h>
    #include <stdio.h>
    
    int something_worked(void) {
        /* thread operation might fail, so here's a silly example */
        void *p = malloc(10);
        free(p);
        return p ? 1 : 0;
    }
    
    void *myThread(void *result)
    {
       if (something_worked()) {
           *((int*)result) = 42;
           pthread_exit(result);
       } else {
           pthread_exit(0);
       }
    }
    
    int main()
    {
       pthread_t tid;
       void *status = 0;
       int result;
    
       pthread_create(&tid, NULL, myThread, &result);
       pthread_join(tid, &status);
    
       if (status != 0) {
           printf("%d\n",result);
       } else {
           printf("thread failed\n");
       }
    
       return 0;
    }
    

    如果必须对结构使用线程出口值,那么必须动态地分配它(并确保连接线程的人释放它)。不过,这并不理想。

        3
  •  18
  •   salsaman    11 年前

    这是一个正确的解决方案。在这种情况下,TData被分配到主线程中,并且有一个空间供线程放置其结果。

    #include <pthread.h>
    #include <stdio.h>
    
    typedef struct thread_data {
       int a;
       int b;
       int result;
    
    } thread_data;
    
    void *myThread(void *arg)
    {
       thread_data *tdata=(thread_data *)arg;
    
       int a=tdata->a;
       int b=tdata->b;
       int result=a+b;
    
       tdata->result=result;
       pthread_exit(NULL);
    }
    
    int main()
    {
       pthread_t tid;
       thread_data tdata;
    
       tdata.a=10;
       tdata.b=32;
    
       pthread_create(&tid, NULL, myThread, (void *)&tdata);
       pthread_join(tid, NULL);
    
       printf("%d + %d = %d\n", tdata.a, tdata.b, tdata.result);   
    
       return 0;
    }
    
        4
  •  3
  •   Messa    9 年前

    我想你得把号码堆起来。这个 int ret 变量在堆栈上,并在函数执行结束时被销毁 myThread .

    void *myThread()
    {
           int *ret = malloc(sizeof(int));
           if (ret == NULL) {
               // ...
           }
           *ret = 42;
           pthread_exit(ret);
    }
    

    别忘了 free 当你不需要它的时候:)

    另一种解决方案是返回指针值形式的数字,如NeilButterworth建议的那样。

        5
  •  2
  •   Maurits Rijk    14 年前

    您正在返回对的引用 雷特 它是堆栈上的变量。

        6
  •  2
  •   Abhishek    10 年前
    #include<stdio.h>
    #include<pthread.h>
    void* myprint(void *x)
    {
     int k = *((int *)x);
     printf("\n Thread created.. value of k [%d]\n",k);
     //k =11;
     pthread_exit((void *)k);
    
    }
    int main()
    {
     pthread_t th1;
     int x =5;
     int *y;
     pthread_create(&th1,NULL,myprint,(void*)&x);
     pthread_join(th1,(void*)&y);
     printf("\n Exit value is [%d]\n",y);
    }  
    
        7
  •  1
  •   Jay    14 年前

    问题:返回/存储多线程变量的最佳实践是什么?全局哈希表?

    这完全取决于你想要返回什么以及你将如何使用它?如果您只想返回线程的状态(比如线程是否完成了它打算做的事情),那么只需使用pthread_exit或使用返回语句从线程函数返回值。

    但是,如果您想要更多的信息用于进一步的处理,那么您可以使用全局数据结构。但是,在这种情况下,您需要使用适当的同步原语来处理并发性问题。或者,您可以分配一些动态内存(对于您希望存储数据的结构更为合适),并通过pthread_exit发送数据,一旦线程加入,您就在另一个全局结构中更新它。这样,只有一个主线程会更新全局结构,并发问题得到解决。但是,您需要确保释放由不同线程分配的所有内存。

        8
  •  0
  •   Aditya    13 年前

    如果您不愿意返回地址,并且只有一个变量(例如要返回的整数值),那么您甚至可以在传递之前将其类型化为(void*),然后在主数据中收集它时,再次将其类型化为(int)。你有这个价值,不会发出难看的警告。