C linux pthread требует сна для работы

Я пишу программу в c linux с помощью gcc. Если я не использую этот оператор сна он будет печатать «созданный поток» 2,3 или 4 раза случайным образом. Может ли кто-нибудь объяснить мне такое поведение? // следующий код - всего лишь образец, я знаю, что не очень полезно создать поток, чтобы просто напечатать строку :)

void* makeRequest(void* arg) {
    printf("Thread created\n");
}

int main(){
   pthread_t thr[10];
   for(i=0; i<3; i++){  
       pthread_create(&thr[i], 0, makeRequest, &i);
       sleep(1);
    }
 }

постскриптум Я включил pthread.h и параметр компиляции -pthread

0
nl ja de

4 ответы

Вы должны присоединить все созданные вами потоки, заканчивая main , когда вы завершаете весь процесс.

В качестве альтернативы вы можете завершить main с помощью pthread_exit .

4
добавлено
Вам просто нужно убедиться, что ваш main не заканчивается ни перед каким другим вашим потоком. Итак, да, соединение должно быть где-то между созданием потоков в цикле для и прекращением main .
добавлено автор Jens Gustedt, источник
поэтому соединение pthread должно быть сделано после этого для утверждения? (моя программа довольно сложна и оператор «для» должен выполняться бесконечно много раз, потому что он ждет запросов клиента, а когда клиентский запрос существует, он создаст 3 потока) while (1) {for (i = 0; i <3; i ++) {pthread_create (& thr [i], 0, makeRequest, & i); сон (1); }}
добавлено автор NiCU, источник

В дополнение к другим замечаниям,

 pthread_create(&thr[i], 0, makeRequest, &i);

is incorrect, because i is a local variable, so &i is the same pointer on all your calls to pthread_create

Обычно вы должны указывать указатель данных на свою нить-процедуру - там, где программа потока является makeRequest либо статическим указателем, либо уникальным указателем (уникальным для каждого потока); на практике, сделать его указателем на некоторые malloc -ed memoory.

Лучшей практикой было бы объявить некоторый struct my_thread_data_st , чтобы однозначно выделить его в кучу с помощью

struct my_thread_data_st* td = malloc(sizeof(struct my_thread_data_st));
if (!td) perror("malloc td"), exit(EXIT_FAILURE);
memset (td, 0, sizeof(struct my_thread_data_st));
// fill td appropriately, then
pthread_create(&thr[i], 0, makeRequest, td);

Or you could have an array of e.g. int-s, e.g. int num[4];, initialize it appropriately, then pthread_create(&thr[i], 0, makeRequest, &num[i]);

Конечно, если td выделен в виде кучи через malloc , не забудьте в free его в соответствующее время, например. после окончания потока (например, после pthread_join ). Вас также может заинтересовать GC Boehm и использовать GC_malloc вместо malloc (тогда не беспокойтесь о освобождении памяти, GC это сделает).

If the threads are accessing a shared data, you should serialize access to it with some [global or static] mutex (using pthread_mutex_lock & pthread_mutex_unlock)

Не забудьте вызвать pthread_join во всех ваших потоках перед выходом из -e.g. возврат из main .

Я предлагаю прочитать учебник pthreads и некоторую книгу по расширенное программирование linux .

2
добавлено
Большое спасибо за ваш очень подробный ответ. Это помогло мне много разделить память кучи. предложение. Еще раз спасибо :)
добавлено автор NiCU, источник

First use join: and no need to send &i if you don't use it.

напечатать «созданный поток» 2,3 или 4 раза случайным образом.

Когда основной поток умирает, все дочерние потоки также умирают. поэтому вам нужно подождать в соединении.

randomly.: because we don't know in thread context switching which will get chance. it may be main-thread or child threads.

for(i=0; i<3; i++){  
       pthread_create(&thr[i], 0, makeRequest, &i);   
}

for(i=0; i<3; i++){  
       pthread_join(thr[i], NULL);
}

Второй используйте -lpthread не -pthread

$ gcc file.c -lpthread -o output      

<Сильный> EDITED

-pthread Adds support for multithreading with the "pthreads" library. This option sets flags for both the preprocessor and linker: Jens Gustedt comment

Difference between -pthread and -lpthread

1
добавлено
@nickNatra: это прекрасно ...
добавлено автор Grijesh Chauhan, источник
@nickNatra, но я не думаю, что созданный поток " напечатан 4 раза, он может быть максимальным 3 раза.
добавлено автор Grijesh Chauhan, источник
@JensGustedt: Ох .. Я не знаю о -pthread :( Я ошибся тогда ... Но я не нашел этот вариант в google-поиске.
добавлено автор Grijesh Chauhan, источник
@JensGustedt: спасибо за эту информацию Jens!
добавлено автор Grijesh Chauhan, источник
@JensGustedt благодарит Йенса! Я обновил свой ответ.
добавлено автор Grijesh Chauhan, источник
@GrijeshChauhan, -pthread - это правильный вариант для gcc. Он делает больше, чем -lpthread : " -pthread Добавляет поддержку многопоточности с помощью библиотеки pthreads. Эта опция устанавливает флаги как для препроцессора, так и для компоновщика."
добавлено автор Jens Gustedt, источник
спасибо за предложение -lpthread, я прочитаю об этом больше. Я знаю, что мне не нужно отправлять этот «i», но, как я уже сказал, это всего лишь образец (весь код имеет около 500 строк)
добавлено автор NiCU, источник

Тебе нужно:

for(i = 0; i < 3; i++)
{
   pthread_join(thr[i], NULL);
}

Как вы его написали, нет ничего, ожидая, когда ваши потоки закончатся до основного возврата и выйдут из всего процесса, убив потоки.

1
добавлено
Linux Help
Linux Help
2 686 участник(ов)

Правила: https://telegra.ph/Pravila-Linux-Help-10-15

Linux Security
Linux Security
652 участник(ов)

Данная группа принципиально про безопасность и в частности про безопасность Linux. Прочие темы просим обсуждать в профильных чатах.

Linux Gaming RUS
Linux Gaming RUS
28 участник(ов)

Русскоязычный чатик, посвящённый играм на различных дистрибутивах Linux, а также wine, proton Arch Linux RU @ArchLinuxChatRU Gnome RU @gnome_ru