POSIX темы в C - PullRequest
       19

POSIX темы в C

2 голосов
/ 21 января 2012

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

Main: Creating thread 0
Main: Creating thread 1
Main: Creating thread 2
Main: Creating thread 3
Main: Creating thread 4
Main: Creating thread 5
Main: Creating thread 6
Main: Creating thread 7
Main: Creating thread 8
Thread 0: English: Hello World!
Thread 0: English: Hello World!
Thread 0: English: Hello World!
Thread 0: English: Hello World!
Thread 0: English: Hello World!
Thread 0: English: Hello World!
Thread 0: English: Hello World!
Thread 0: English: Hello World!
Thread 0: English: Hello World!

Но каждый поток должен сказать «Hello World» на другом языке. Вот мой код Он отлично работает, когда четвертый параметр в функции pthread_create - это просто (void *) t вместо указателя. Но я знаю, что правильное решение с (void *) &t. Возможно, я имею дело с некоторой проблемой указателя, но я просто не вижу пути ...

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

#define NUM_THREADS 8

char *messages[NUM_THREADS + 1] = 
{
   "English: Hello World!",
   "French: Bonjour, le monde!",
   "Spanish: Hola al mundo",
   "Klingon: Nuq neH!",
   "German: Guten Tag, Welt!",
   "Russian: Zdravstvytye, mir!",
   "Japan: Sekai e konnichiwa!",
   "Latin: Orbis, te saluto!",
   "Cesky: Ahoj svete!"
};


void * helloThread ( void * threadid )
{
   int *id_ptr, taskid;

   sleep(1);
   id_ptr = (int *) threadid;
   taskid = *id_ptr;
   printf("Thread %d: %s\n", taskid, messages[taskid]);
   return(NULL);
}

int main(int argc, char *argv[])
{
   pthread_t threads[NUM_THREADS];
   int rc, t;

   for(t=0;t<=NUM_THREADS;t++) {
      printf("Main: Creating thread %d\n", t);
      rc = pthread_create(&threads[t], NULL, helloThread, (void *) &t );
      if (rc) {
         printf("ERROR; return code from pthread_create() is %d\n", rc);
         return (EXIT_FAILURE);
      }
  }

   pthread_exit(NULL);
   return ( 0 );
}

Ответы [ 3 ]

5 голосов
/ 21 января 2012

Есть несколько неправильных вещей:

Во-первых, вы переступаете границы;цикл должен сказать for(t = 0; t < NUM_THREADS; t++).

Во-вторых, вы должны присоединиться или отсоединить потоки, прежде чем завершить процесс, так что скажите это в конце:один и тот же указатель (а именно &t) на все потоки.Мало того, что это дает вам неправильное поведение, но это также подвергает вас неопределенному поведению из-за условий гонки или разыменования висячих указателей.Вместо этого предоставьте каждому потоку свою собственную память:

int q[NUM_THREADS];  /* dedicated storage for each thread! */

for(t = 0; t < NUM_THREADS; ++t) {
   printf("Main: Creating thread %d\n", t);
   q[t] = t;
   rc = pthread_create(threads + t, NULL, helloThread, q + t);
   /* ... */
}

(В-четвертых, вы не должны вызывать pthread_exit так, как вы делаете, чтобы завершить основной поток. Это не нужно и не позволяет вам вернутьсяmain() обычным способом.)

1 голос
/ 21 января 2012

Вы передаете указатель на итератор цикла t в main().

Когда цикл увеличивает значение итератора ... ваши запущенные потоки видят все, что есть в данный момент. Поскольку все ваши потоки будут ждать одну секунду, прежде чем что-то делать, и вы выходите из main(), не дожидаясь завершения потоков, то то, на что вы указываете, больше не действует и все, что вы видите, будет неопределенным поведением. .

0 голосов
/ 21 января 2012

&t передает указатель на переменную t в поток.Поскольку каждый поток получает указатель на одну и ту же переменную (t), значение в каждом потоке будет одинаковым в любой момент времени.

Простое решение:

pthread_t threads[NUM_THREADS];
int thread_ids[NUM_THREADS]; // array which will hold the ID of each thread
int rc, t;

for(t=0;t<NUM_THREADS;t++) { // fixed
  printf("Main: Creating thread %d\n", t);
  thread_ids[t] = t; // setting the thread id
  rc = pthread_create(&threads[t], NULL, helloThread, (void *) &thread_ids[t] );
  // notice that I use &threads_ids[t] instead of &t
  if (rc) {
    printf("ERROR; return code from pthread_create() is %d\n", rc);
    return (EXIT_FAILURE);
  }
}
...