【问题标题】:variable as argument in pthreads [duplicate]变量作为pthreads中的参数[重复]
【发布时间】:2017-12-11 05:27:52
【问题描述】:

我编写了一个创建线程数的程序。该数字可以作为命令行参数传递或默认值为 5。我面临的问题是打印作为参数传递给 pthread writer 函数的线程号。

下面是我的程序:

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

void *writerThread(void *args)
{
  int id = *((int *)args);
  printf("In thread %d\n", id);
}

int main(int argc, char *argv[])
{
  int numThreads;
  if(argc != 2)
    numThreads = 5;
  else
    numThreads = atoi(argv[1]);

  pthread_t *tId = (pthread_t*) malloc(sizeof(pthread_t) * numThreads);

  int i;
  for(i = 0; i < numThreads; i++)
  {
    pthread_create(&tId[i], NULL , writerThread, &i);
  }

  // wait for threads
  for(i = 0; i < numThreads; i++)
    pthread_join(tId[i], NULL);

  if(tId)
    free(tId);

  return 0;
}

输出:

In thread 2
In thread 0
In thread 3
In thread 2
In thread 0

为什么 0 和 2 会出现两次? 任何帮助将不胜感激。

【问题讨论】:

  • 您必须确保每个线程都有自己的单独变量,因为无法保证指向的数据与您在线程开始运行时预期的数据相同。所以,你需要一个线程号数组,并为每个(int thr_num[numThreads]; … { thr_num[i] = i; pthread_create(…, &amp;thr_num[i]); })传递一个不同的条目。而且,除非你认为线程数会非常高,否则我会使用 VLA,甚至是固定大小的数组,的pthread_t 结构——类似于之前建议的thr_num 数组。或者使用pthread_t 和int 创建一个结构数组。

标签: c pthreads


【解决方案1】:

为了补充Ring Ø's answer,在将一个小整数传递给线程例程的特殊情况下,您可以强制转换为intptr_t 类型该参数和代码:

void *writerThread(void *args) {
  int id = (int)((intptr_t)arg);
  printf("In thread %d\n", id);
}

然后

for(i = 0; i < numThreads; i++) {
   pthread_create(&tId[i], NULL , writerThread, (void*)((intptr_t)i));
}

这是可能的,因为 pthread_create 只是传递了一个 uninterpreted [pointer] 字,它实际上可能是来自 intptr_t 的转换,保证与指针具有相同的大小。

所以你并不总是需要pthread_create 的最后一个参数是一个有效(可解除引用)指针。

顺便说一句,在我的 Linux/Debian/x86-64 系统上,指针(例如 void*)和 intptr_t 有(如 long)8 个字节,但 int 是 4 个字节。

在通常情况下,pthread_create 的最后一个参数通常(根据经验)是指向某个 heap allocatedmalloc-ed 区域的唯一指针(您应该稍后适当地 free 它,通常在相应的pthread_join 之后)。

请注意,您的代码应该针对 malloc 的失败进行测试,并且应该:

 pthread_t *tId = malloc(sizeof(pthread_t) * numThreads);
 if (tId == NULL) { perror("malloc tId"); exit(EXIT_FAILURE); };

因为在malloc 失败的不太可能的情况下,您的代码会显示undefined behavior,因为pthread_create 的第一个参数应该是某个pthread_t 的有效地址。

【讨论】:

  • 好像回答的次数还不够多!
  • 您标记为重复的几个答案没有提到intptr_t 转换技巧(特定于将整数传递给线程例程的情况)。所以我认为我的回答不值得你投反对票。
【解决方案2】:

创建线程时

pthread_create(&tId[i], NULL , writerThread, &i);

i 继续它的生命......因此,当您在线程中打印 *(int*)args 时。您将获得i 的当前值,该值在 main 函数中一直被使用和更改。

您可能希望分配一个包含线程 id 的整数数组并在线程创建期间存储该 id

int tids[numThreads];
for(i = 0; i < numThreads; i++) {
   tids[i] = i;
   pthread_create(&tId[i], NULL , writerThread, &tids[i]);
}

这样,每个线程都有一个指向它自己的个人数据的参数(在这种情况下,是一个整数)。

【讨论】:

    猜你喜欢
    • 2019-12-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-30
    • 1970-01-01
    • 2015-10-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多