Почему pthread_join не закрывает массив потоков должным образом в этом примере? - PullRequest
1 голос
/ 26 октября 2011

Я пытаюсь научить себя многопоточности. У меня есть следующий источник, который компилируется и работает правильно:

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

#define PTHREAD_COUNT 10
#define FREQ 5

void *thread_function(void *arg) {
  int *incoming = (int *)arg;
  int freqIdx;

  for (freqIdx = 0; freqIdx < FREQ; freqIdx++)
    fprintf(stdout, "Hello, world (thread %d)\n", *incoming);

  return NULL;
}

int main(int argc, char **argv) {
  pthread_t thread_IDs[PTHREAD_COUNT];
  void *exit_status;
  int threadIdx;

  for (threadIdx = 0; threadIdx < PTHREAD_COUNT; threadIdx++) {
    pthread_create(&thread_IDs[threadIdx], NULL, thread_function, &threadIdx);
    pthread_join(thread_IDs[threadIdx], &exit_status);
  }

  return 0;
}

Я получаю следующий результат:

Hello, world (thread 0)
Hello, world (thread 0)
Hello, world (thread 0)
Hello, world (thread 0)
Hello, world (thread 0)
Hello, world (thread 1)
...
Hello, world (thread 9)

Если я pthread_create массив pthread_t наберет в цикле, а затем pthread_join в отдельном цикле, то произойдет сбой:

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

#define PTHREAD_COUNT 10
#define FREQ 5

void *thread_function(void *arg) {
  int *incoming = (int *)arg;
  int freqIdx;

  for (freqIdx = 0; freqIdx < FREQ; freqIdx++)
    fprintf(stdout, "Hello, world (thread %d)\n", *incoming);

  return NULL;
}

int main(int argc, char **argv) {
  pthread_t thread_IDs[PTHREAD_COUNT];
  void *exit_status;
  int threadIdx;

  /* here I split the thread _create and _join steps into separate loops */

  for (threadIdx = 0; threadIdx < PTHREAD_COUNT; threadIdx++)
    pthread_create(&thread_IDs[threadIdx], NULL, thread_function, &threadIdx);

  for (threadIdx = 0; threadIdx < PTHREAD_COUNT; threadIdx++)
    pthread_join(thread_IDs[threadIdx], &exit_status);

  return 0;
}

Вывод из этого совершенно неверный. Вместо того, чтобы получать по пять fprintf операторов из каждого потока, я получаю один или два, скажем, из потоков 2 и 3 и около 20-25 Hello, world операторов из потока 0.

Почему это не получается?

Ответы [ 3 ]

2 голосов
/ 26 октября 2011

Одна проблема, которую я вижу, это то, что вы даете ей адрес локальной переменной threadIdx. Когда вы изменяете его в цикле, значение, которое видит поток, также изменяется. Поэтому значение threadIdx не будет правильным.

Во 2-м цикле вы снова устанавливаете threadIdx на 0 и ждете окончания потоков, что объясняет, почему вы видите, что многие из них вместо этого выводят нить 0.

Вы можете просто передать threadIdx и затем вместо этого интерпретировать аргументы void * как int (поскольку sizeof (int) <= sizeof (void *) и обычно гарантируется на большинстве машин), и вы должны получить правильный вывод. </p>

1 голос
/ 26 октября 2011

Как уже говорили другие, ваша проблема заключается в том, чтобы разделить одну переменную threadIdx между всеми потоками. Один из способов исправить это - создать одну переменную на поток:

int threadIdx;
int indexes[PTHREAD_COUNT];

for (threadIdx = 0; threadIdx < PTHREAD_COUNT; threadIdx++) {
    indexes[threadIdx] = threadIdx;
    pthread_create(&thread_IDs[threadIdx], NULL, thread_function, &indexes[threadIdx]);
}
1 голос
/ 26 октября 2011

Вы передаете указатель на одну и ту же переменную threadIdx во все потоки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...