pthread_cond_broadcast не сигнализирует о потоках - PullRequest
0 голосов
/ 05 июня 2018

Я действительно пытаюсь понять, как блокировать и разблокировать мьютексы таким образом, чтобы потоки могли работать одновременно.Сейчас я пытаюсь заставить каждый поток что-то сделать, затем подождать, пока все потоки не будут готовы, и затем повторить это.Это должно происходить неоднократно, поэтому у меня все это в условном цикле.Моя проблема в том, что кажется, что моя трансляция никогда не принимается никакими потоками, так как каждый поток, который ждет сигнала, ждет вечно, в то время как поток, который отправил сигнал, продолжается.сделать это как можно проще, оставаясь компилируемым и запускаемым:

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

#define num_threads 4

int repeat = 1;
int timesLooped = 0;
int waitingThreads = 0;
int threadNo = -1;
pthread_mutex_t mutex1;
pthread_cond_t condition;


//thread body
void* threadBody(void* arg){


   //sensitive info: requires lock
   if(pthread_mutex_lock(&mutex1)){ printf("error1\n"); }
     threadNo++;
     int threadId = threadNo;
     //other info is set here as well in my code
   if(pthread_mutex_unlock(&mutex1)){ printf("error2\n"); }

   //main loop in the thread body
   while(repeat == 1){

      if(pthread_mutex_lock(&mutex1)){ printf("error3\n"); }

      //wait until all threads are ready
      while(waitingThreads < num_threads - 1){

         printf(" %d! ", threadId);
         waitingThreads++;
         pthread_cond_wait(&condition, &mutex1);

         printf(" %d ", threadId);
         if(pthread_mutex_unlock(&mutex1)){ printf("error4\n"); }

      }

      //last thread will broadcast
      if(waitingThreads == num_threads - 1){

         printf("\n\nthread %d was last! broadcasting to let everyone proceed...", threadId);
         timesLooped++;
         waitingThreads = 0;
        if(timesLooped == 3){
            repeat = 0;
         }
sleep(1);
         pthread_cond_broadcast(&condition);
         if(pthread_mutex_unlock(&mutex1)){ printf("error5\n"); }





      }



   }
printf("\n\nexiting thread %d\n", threadId);
   pthread_exit((void*) arg);
}





int main(int argc, char** argv){

   pthread_t threads[num_threads];
   void* retval;

   //create threads
   for(long i = 0; i < num_threads; i++){
      pthread_create(&threads[i], NULL, threadBody, (void*) i);
   }

   //join threads
   for(long j = 0; j < num_threads; j++){
      pthread_join(threads[j], &retval);
   }


printf("\n\nDONE\n");
}

Это дает мне вывод:

поток 3 был последним!вещание, чтобы позволить всем продолжить ...

тема 2 была последней!вещание, чтобы позволить всем продолжить ...

тема 1 была последней!широковещательная рассылка, чтобы все могли продолжить ...

выход из потока 1 (тупик, другие потоки никогда не выходят)

1 Ответ

0 голосов
/ 05 июня 2018

В вашей программе есть как минимум две ошибки.

  1. У вас есть гонка данных (см. сообщение в блоге ).

    Когдапотоки 0 - num_threads - 1 получают доступ waitingThreads в if (waitingThreads == num_threads - 1) ..., они делают это вне блокировки (т. е. участвуют в гонке).

  2. Нельзя разрешать потоки, кромепоследний запускаемый (это ваш основной вопрос).

    pthread_cond_wait возвращается, когда оба условия были сигнализированы и мьютекс может быть повторно получен.

    Но ваш последний поток немедленно повторно получает мьютекс после его освобождения, поэтому никакой другой поток не может продолжить.

    Я ожидаю, что если вы добавите sleep или usleep после pthread_mutex_unlock в последнем потоке ваша программа начнет работать так, как вы ожидаете.

...