Многопоточное тестирование C приложение зависает, если не используется printf - PullRequest
2 голосов
/ 15 апреля 2020

Я пытаюсь изучить входы и выходы из многопоточности в C. Я начал с этого небольшого примера:

#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> //Header file for sleep(). man 3 sleep for details. 
#include <pthread.h> 

#define TOTAL_TS  1000
#define WAIT_TS   74

int timeStepCounter;

// A normal C function that is executed as a thread 
// when its name is specified in pthread_create() 
void *longProcess(void *vargp) 
{ 
   int endtime = timeStepCounter + WAIT_TS;
    while (timeStepCounter < endtime);
    printf("Finished when timeStepCounter is %d\n",timeStepCounter); 
    return NULL; 
} 

int main() 
{ 

   pthread_t thread_id; 

   for (timeStepCounter = 0; timeStepCounter < TOTAL_TS; timeStepCounter++){
      if (timeStepCounter == 158){         
         printf("Creating thread @ %d\n",timeStepCounter);
         pthread_create(&thread_id, NULL, longProcess, NULL); 
      }    
      //printf("TimeStep is: %d\n",timeStepCounter);
   }

   pthread_join(thread_id, NULL); 
   printf("Finished\n"); 

   return 0;

}

Я изменил его из примера inte rnet.

Итак, вот что происходит. Когда вы запускаете его как есть, программа зависает после печати сообщения «Создание потока ...».

Если, однако, я раскомментирую printf, который печатает TimeStep, приложение работает должным образом.

Итак, мой вопрос, почему?

РЕДАКТИРОВАТЬ: В соответствии с предложением @Bodo я помещаю ссылку на пример inte rnet, который послужил основой для моего кода: https://www.geeksforgeeks.org/multithreading-c-2/

1 Ответ

0 голосов
/ 15 апреля 2020

Как уже упоминалось в комментарии groo , программа не будет работать правильно, если вновь созданный поток начинает выполнение, когда основной поток уже завершил l oop.

Это вероятно, происходит, когда основной поток не задерживается при вызове printf.

Добавьте строку

printf("Thread started when timeStepCounter is %d\n",timeStepCounter);

до

while (timeStepCounter < endtime);

и вы, вероятно, увидите

Thread started when timeStepCounter is 1000

Кроме того, вы должны объявить переменные, к которым обращается более одного потока, как volatile, то есть

volatile int timeStepCounter;

, и убедиться, что он использует тип с доступом atomi c , (Если бы не было Atomi c, вам потребовалась бы синхронизация.)

Даже если только один поток изменяет значение, компилятор с оптимизацией обнаружит, что timeStepCounter не изменяется в l oop

while (timeStepCounter < endtime);

и создайте код, подобный

while(1);

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

Я могу убедиться в этом, скомпилировав код без volatile и с некомментированным printf с

gcc -g -Wall -Wextra -pedantic -O3    test.c  -lpthread -o test

Я получаю, например,

...
Creating thread @ 158
...
Thread started when timeStepCounter is 226
...

но нет

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