#c #pthreads
#c #pthreads
Вопрос:
Я пытаюсь научить себя потоковой обработке pthreads. У меня есть следующий исходный код, который компилируется и запускается должным образом:
#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(amp;thread_IDs[threadIdx], NULL, thread_function, amp;threadIdx);
pthread_join(thread_IDs[threadIdx], amp;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(amp;thread_IDs[threadIdx], NULL, thread_function, amp;threadIdx);
for (threadIdx = 0; threadIdx < PTHREAD_COUNT; threadIdx )
pthread_join(thread_IDs[threadIdx], amp;exit_status);
return 0;
}
Результат этого совершенно неверен. Вместо получения пяти fprintf
операторов из каждого потока я получаю один или два, скажем, из потоков 2 и 3, и примерно от 20 до 25 Hello, world
операторов из потока 0.
Почему это не удается?
Ответ №1:
Одна из проблем, которую я вижу, заключается в том, что вы даете ему адрес локальной переменной threadIdx . Когда вы изменяете его в цикле, значение, которое видит поток, также изменяется. Таким образом, значение threadIdx не будет правильным.
Во 2-м цикле вы снова устанавливаете threadIdx равным 0 и ждете завершения потоков, что объясняет, почему вы видите, что многие из них печатают поток 0 вместо этого.
Вы можете просто передать threadIdx, а затем интерпретировать аргументы void * вместо этого как int (потому что sizeof(int) <= sizeof(void *) и обычно гарантируется на большинстве машин), и вы должны получить правильный вывод.
Ответ №2:
Как указывали другие, ваша проблема заключается в разделении одной threadIdx
переменной между всеми потоками. Один из способов исправить это — создать одну переменную для каждого потока:
int threadIdx;
int indexes[PTHREAD_COUNT];
for (threadIdx = 0; threadIdx < PTHREAD_COUNT; threadIdx ) {
indexes[threadIdx] = threadIdx;
pthread_create(amp;thread_IDs[threadIdx], NULL, thread_function, amp;indexes[threadIdx]);
}
Ответ №3:
Вы передаете указатель на одну и ту же threadIdx
переменную всем потокам.