C - 创建 n 个线程

标签 c linux pthreads pthread-join

我正在研究以下功能。这个函数应该创建 n 个线程。它还应该打印子线程的 tid。但此刻我有点困惑。当我执行它时,例如我创建了 5 个线程,它始终返回相同的 tid。据我了解,tid 是调用者的线程 ID。是同一个调用者调用了所有这些线程还是我做错了什么。 这是代码:

void spawnThreads( unsigned int n) {
   int threads = n, ret = -1;
   pthread_t * thread = malloc(sizeof(pthread_t)*threads);
   pid_t tid;
   int i;
   for(i = 0; i < threads; i++) {
       ret = pthread_creation(&thread[i], NULL, (void *(*)(void *)) foo, NULL); // foo does not do anything

       if( ret != 0) {
           printf("pthread error!\n");
       }

       tid = syscall(SYS_gettid);
       printf("%d %d\n", i, tid);
       printf("I just created thread %d\n", i);

       pthread_join(thread[i],NULL);
}

void * foo(void) {
    return NULL;
}

例如,我得到以下输入的 spawnThreads(4) 以下输出:

 0 2411
 I just created thread 0

 1 2411
 I just created thread 1

 2 2411
 I just created thread 2

 3 2411
 I just created thread 3

总而言之,函数应该打印>i< >tid<>tid<表示 child 的TID,>i<从1到n。

但为什么我得到四次相同的 tid?我做错什么了?如果有人能向我解释哪里出了问题,我将不胜感激。

最佳答案

您为每个线程获得相同 TID 的原因是您每次都从主线程调用 syscall(SYS_gettid),而不是从您创建的新线程中调用。您需要从线程函数内部调用它,然后提供一种方法将信息传回主线程(如果需要的话)。

作为一种方法的示例(省略了一些错误检查):

创建一个结构来保存互斥锁、条件、TID 和一个标志以指示 TID 何时有效。

struct s_threadId {
  pthread_mutex_t   mtx;    /* mutex & condition to allow main thread to
                               wait for the new thread to  set its TID */
  pthread_cond_t    cond;   /* '' */
  pid_t             id;     /* to hold new thread's TID */
  int               ready;  /* to indicate when 'id' is valid, in case
                               the condition wait gets interrupted */
};

然后将您的线程函数更改为锁定、设置和发出信号(并移动它以使其声明在之前 spawnThreads() 可见):

void *foo(void *arg)
{
  struct s_threadId *thId = arg;

  /* Lock mutex... */
  pthread_mutex_lock(&thId->mtx);

  /* Get and save TID and ready flag.. */
  thId->id = syscall(SYS_gettid);
  thId->ready = 1;
  /* ..and signal main thread that we're ready */
  pthread_cond_signal(&thId->cond);

  /* ..then unlock when we're done. */
  pthread_mutex_unlock(&thId->mtx);

  /* ... */

  return NULL;
}

...并修改您的 spawnThreads 函数以初始化/清理结构成员并在线程设置后获取 TID:

void spawnThreads(unsigned int n)
{
  pthread_t thread; /* reused for each thread, since they run 1 at a time */

  /* struct to pass back TID */
  struct s_threadId threadId;
  pthread_cond_init(&threadId.cond, NULL);  /* init condition */
  pthread_mutex_init(&threadId.mtx, NULL);  /* init mutex */

  int i;
  for (i = 0; i < n; i++) {
    /* lock mutex *before* creating the thread, to make the new thread
       wait until we're ready before signaling us */
    pthread_mutex_lock(&threadId.mtx);

    /* clear ready flag before creating each thread */
    threadId.ready = 0;
    /* create threads and pass address of struct as argument */
    if (pthread_create(&thread, NULL, foo, &threadId)) {
      printf("pthread error!\n");
    } else {
      /* Wait on the condition until the ready flag is set */
      while (!threadId.ready) {
        pthread_cond_wait(&threadId.cond, &threadId.mtx);
      }
      /* Now we have the TID... */
      printf("%d %d\n", i, threadId.id);
      printf("I just created thread %d\n", i);
    }
    /* ..and unlock the mutex when done. */
    pthread_mutex_unlock(&threadId.mtx);

    pthread_join(thread, NULL);
  }

  /* When we're completely done with the struct we need to clean up the
     mutex and condition variable */
  pthread_mutex_destroy(&threadId.mtx);
  pthread_cond_destroy(&threadId.cond);
}

在上面,需要互斥锁和条件等待来确保主线程在新线程有机会设置它之前不会尝试打印 TID。主线程启动新线程,然后等待,新线程在完成存储 TID 后发出信号,以便主线程可以继续。

关于C - 创建 n 个线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20276010/

相关文章:

c - 多线程程序中的双重释放或损坏

c - 某些线程返回垃圾值?

c - 什么时候将值隐式转换为指针?

python - 在 Linux 上将 Spyder 与 Python 2.7 和 Python 3 结合使用

linux - 通过 HTTP 运行更高权限命令的合适方法是什么

linux - Apache 未在 CentOS 7 服务器上运行

c - 多线程,id不起作用,如何添加其他功能

c - MPI_Gatherv : Garbage values received in root's array

c++ - 在 GCC 中使用 -O3 有什么缺点吗?

c - 引擎功能 : Calling MATLAB from a C application