Я изучаю многопоточные программы и ожидаю, что следующий фрагмент кода будет бесконечным циклом печати " foo"
вместо этого ничего не произойдет
Ожидания:
foofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoo
Реальность:
Как будто нить даже не создается, что я делаю неправильно??? Как создать поток, который будет выполнять любую функцию, назначенную ему
Исходный код
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <iostream>
void* print(void*);
struct threadInfo
{
int threadID;
int threadNo;
};
int main()
{
pthread_t thread[3];
bool cont = false;
int i = 1;
int max = 3;
while ( cont == false )
{
if ( i <= max )
{
threadInfo t_info;
t_info.threadID = i ;
t_info.threadNo = i ;
pthread_create(&thread[i-1],NULL,print,(void*)&t_info);
i++;
}
}
}
void* print(void* arg)
{
std::cout << "Foo" ;
pthread_exit(NULL);
}
Следующий фрагмент кода компилируется в командной строке Ubuntu со следующей командой
g++ test.cpp -o test -lpthread
Нити создаются, но прежде чем они смогут работать, главный поток завершается, и ваша программа завершается (это также UB). Вы должны ждать своих потоков: pthread_join
Время while ( cont == false )
не требуется.
Мой о, мой... С чего начать?
Причина, почему вы ничего не заметили от Joachim Pileborg: нити созданы правильно и выполняют свою работу, но так как ваша основная программа никогда не выходит и никто никогда не выводит линейный фид, вывод с линейной буферой никогда не будет очищено.
Ваша основная программа тратит процессорный цикл на флаг, который никогда не будет изменен. Попытка синхронизировать потоки с флагами очень плоха, несмотря на глупые новые расширения С++ 11, которые делают атомарные переменные альфа-и омегой программирования потоков.
Вы должны использовать какую-то синхронизацию, чтобы ждать окончания потоков. Самый обычный механизм - pthread_join
.
Передача одного и того же экземпляра параметров каждому экземпляру вашего потока создает идеальное состояние гонки. У вас нет гарантии, что поток будет читать параметры в вашем предполагаемом порядке (т.е. до того, как основной цикл изменит их, чтобы подготовиться к запуску следующего потока). Вы должны передать каждому потоку свой собственный частный экземпляр t_info
(или настроить какой-то механизм синхронизации по этой структуре).
Даже после устранения всех этих проблем вы должны ожидать только 3 "Foo", так как каждый поток выходит после одной печати.
И поскольку вы не сериализуете доступ к cout
(т. cout
Вы не защищаете их каким-то синхронным объектом, например мьютексом), возможно, что ваши различные потоки будут беспорядочно перемешаны (т.е. вы могли видеть что-то вроде "FoFFooooo").
if ( i <= max )
предотвращает создание более 3-х потоков.
Там ничего не напечатано, потому что выходные буферы не сбрасываются.
В функции print
выполните, например,
std::cout << "Foo" << std::flush;
Основной поток, вероятно, заканчивается (и третирует все остальные темы этим), прежде чем какой-либо другой поток распечатает что-либо.
Чтобы исправить это, сделайте основной цикл соединения join loop (pthread_join()
для всех созданных нитей) для всех остальных потоков до окончания или завершите основной поток, используя pthread_exit()
.
Также передавая адрес того же экземпляра struct threadInfo
каждый протектор (то есть: (void*)&t_info
) скорее всего не то, что вы хотите.
В pthreads нет ничего плохого. Если вы хотите обеспечить последовательность на выходе, вам необходимо приложить строку распечатки с помощью блокировки и флеша, чтобы вы обеспечили это,
1. A thread only finishes once the message has actually been printed out
2. Threads wait for each other so that no two threads write to the output at the same time