【问题标题】:Simple multithreading in CC中的简单多线程
【发布时间】:2022-01-10 22:15:53
【问题描述】:

我尝试实现一个打印每个线程号的函数。例如线程 0 打印 0 线程 1 打印 1 等等,但不是按照这个预期的顺序。

到目前为止我一直在尝试的是这个

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
void *foo(void *arg){
    int *myid = (int*) arg;
    printf("Hello from thread %d\n",*myid);
    return NULL;
}
int main(void){
   pthread_t tid[4];
   int i;
   for(i=0;i<4;i++){
       pthread_create(&tid[i],NULL,(void*) foo, &i);
  
   }
   for(i=0;i<4;i++){
       pthread_join(tid[i],NULL);
   }
   return 0;
}

但是,这几乎每次都会从线程 0 打印四次 Hello。如何修改此代码以便正确打印每个线程?

【问题讨论】:

  • 不要从线程函数返回NULL,使用pthread_exit
  • 您将循环索引的地址i 传递给foo。例如,如果在循环完成之后之前没有线程真正启动foo,会发生什么?
  • @kiner_shah pthread_exit() 有助于将线程从更深层次的函数调用(不是顶级线程函数)中分离出来。它与任何地方的exit()main() 中的return 相同。
  • @TedLyngmo,它真的在那里,奇怪的是我不知何故错过了它。
  • @kiner_shah 这是关于您的评论«否则没有该功能存在的意义»。如果 return 是离开线程的唯一选择,那么我们不能决定从该线程调用的另一个函数中离开该线程(我并不是说我会这样做,但pthread_exit() 存在这种可能性)。

标签: c multithreading


【解决方案1】:

您将i 的地址传递给每个线程,因此它们每个都读取i 的当前状态(并且没有同步,因此如果不是未定义,结果是不可预测的)。

相反,您需要传递一个指向线程特定数据的指针(其生命周期至少与线程一样长)。例如:

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
void *foo(void *arg){
    int *myid = (int*) arg;
    printf("Hello from thread %d\n",*myid);
    return NULL;
}
int main(void){
   pthread_t tid[4];
   int ids[4];
   int i;
   for(i=0;i<4;i++){
       ids[i] = i;
       pthread_create(&tid[i],NULL,(void*) foo, &ids[i]);
  
   }
   for(i=0;i<4;i++){
       pthread_join(tid[i],NULL);
   }
   return 0;
}

【讨论】:

  • 我建议你检查pthread_createpthread_join的返回值。
【解决方案2】:

这是所有线程共享相同数据的典型情况,但不应该。

在这里,您将&amp;i 传递给每个线程,因此它们都引用内存中的相同位置:唯一存储单个变量i 的位置。 您需要传递一个 ,但在 pthread API 中这并不容易,因为需要一个指针 (void *)。

一种策略是预先为每个线程准备一个具有不同元素的数组,并将第 n 个元素的地址传递给第 n 个线程。

另一种策略是在循环的每次迭代中动态分配一条新信息(此处为int),对其进行初始化(例如使用计数器)并将此地址传递给线程。 然后线程必须在离开之前free() 它自己的一条信息。 这种策略比以前的策略更重。

请注意,有时我们会在代码中看到一个丑陋的快捷方式,只是传递一个 int。 在呼叫站点您传递(void *)(intptr_t)i,在线程中您返回(int)(intptr_t)arg。 诀窍是我们将指针视为一个非常大的整数,因此我们来回转换。 对于一些严肃的代码,我不建议这样做,仅用于快速实验。

【讨论】:

  • 有道理,谢谢!
猜你喜欢
  • 2011-03-16
  • 1970-01-01
  • 1970-01-01
  • 2010-10-10
  • 2011-05-09
  • 2015-08-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多