Função pthread_join em linguagem C com exemplos de threads únicos e múltiplos

Função pthread_join em linguagem C com exemplos de threads únicos e múltiplos
O idioma C oferece a possibilidade de desenvolver os programas de multitarefa usando a biblioteca PTHread do padrão POSIX. Este método aumenta a velocidade do programa acabado, executando vários tópicos em paralelo com a função principal.

Para criar um programa de sucesso usando este método de programação, você deve fazer algumas considerações especiais. Por exemplo, se os tempos de execução de um thread forem mais longos que os da função principal () e for totalmente executados, o programa terá rescindir e todos os tópicos associados, se eles concluíram sua tarefa ou não.

Isso pode causar problemas críticos, porque um tópico que termina inesperadamente pode estar no processo de salvar dados gerados pelo usuário, escrever em um arquivo ou dispositivo ou executar alguma outra tarefa importante.

Neste artigo da dica do Linux, você aprenderá como usar a função pthread_join () para garantir que um ou mais threads sejam encerrados de forma confiável antes de um programa sair ou retomar.

Sintaxe da função pthread_join () na linguagem C

int pThread_join (thread pthread_t, void ** retval);

Descrição da função pthread_join () na linguagem C

A função pthread_join () aguarda o processo do qual é chamado até que um tópico termine sua tarefa. Esta função suspende a função da qual é chamada até o subprocesso especificado por seu identificador no argumento de entrada do encadeamento termina.

Depois que o tópico terminar sua tarefa, o programa retoma a execução da próxima linha do código que chama o Pthread_join ().

Quando o subprocesso termina, a função pthread_join () retorna o status de saída do thread no argumento retval.

Em seguida, vemos os argumentos de entrada para o pthread_join (), juntamente com uma descrição da função que satisfaz cada um desses argumentos:

fio: Este argumento de entrada é um valor de dados do tipo pthread_t e é o identificador do subprocesso que a função pthread_join () deve esperar.

O valor do identificador é gerado pelo sistema e é obtido como resultado da função pthread_create () em seu tópico de argumento de saída quando o thread é criado.

retval: Este argumento de entrada é um ponteiro para (void *) onde a função pthread_join () armazena o status de saída do thread.

Se Pthread_join () retornar com sucesso, ele retornará 0 como resultado. Se ocorrer um erro, essa função retorna um número inteiro com um valor que representa o erro que ocorreu. Mais tarde, você verá uma seção especial que descreve todos os erros que essa função pode gerar e como identificá -los.

A função pthread_join () é definida no pThread.h cabeçalho. Para usá -lo, os seguintes cabeçalhos devem ser incluídos no “.Arquivo C ”, conforme mostrado no seguinte:

#incluir
#incluir

Nota: É importante que você use esse recurso somente quando necessário, pois pode estender o tempo de execução de um programa, interrompendo um processo para esperar o outro para concluir.

Erros de compilação em programas com threads

Ao compilar os programas GCC que usam threads, a compilação pode falhar se não for feita corretamente na linha de comando.

A mensagem de erro mais comum que é emitida pelo compilador afirma que uma das funções do encadeamento a que nos referimos no código não é definida.

Esses erros geralmente resultam em desperdiçar um tempo valioso para verificar os cabeçalhos que inserimos no código, sua integridade e os diretórios associados ao compilador, pois tudo indica que o problema está lá.

Embora as funções que causam o erro sejam definidas no “pThread.H ”Cabeçalho e estão incluídos no código, o compilador não reconhece essas funções, a menos que a biblioteca Pthread seja chamada da linha de comando durante a compilação.

Na ilustração a seguir, você pode ver a maneira correta de chamar a biblioteca Pthread (destacada em verde) do console de comando durante a compilação de programas com threads:

~ $ gcc -phread caminho/nome de arquivo.C -O out_name

Como podemos ver na figura a seguir, o erro desaparece quando a biblioteca PTHread é chamada durante a compilação.

Como usar a função pthread_join () para aguardar um tópico para concluir a execução no idioma C

Neste exemplo, criamos um tópico que tem um tempo de execução mais longo que a função principal (). Depois de criarmos o tópico, usamos o pthread_join () para aguardar toda a execução do thread antes de sair da função principal () e encerrar o programa.

Para esse fim, criamos a função Thread_f () que executa o thread. Esta função é um loop "para" com 5 ciclos de uma segunda duração, cada um dos quais imprime o "Segundos até o fim do tópico:”Mensagem, seguida pelo número de segundos restantes no console de comando.

Da função Main (), criamos o Thread_1 com a função pthread_create (). Em seguida, chamamos a função pthread_join () para aguardar o subprocesso para concluir a execução antes de sair do programa.

A chamada de função pthread_join () acompanha o identificador Thread_1 como o primeiro argumento de entrada e o retval como nulo no segundo argumento. Vemos o seguinte código completo para este exemplo:

#incluir
#incluir
#incluir
#incluir
void* thread_f (void* n);
int main ()

pthread_t thread_1;
pthread_create (& thread_1, null, thread_f, null);
pthread_join (thread_1, nulo);
retornar 0;

void* thread_f (void* n)

para (int a = 5; a!= 0; a--)

printf ("segundos até o final do thread: %i \ n", a);
sono (1);

printf ("End of Thread \ n");
pthread_exit (n);

A imagem a seguir mostra a compilação e execução deste código:

Como vimos na figura, o loop "para" completou seus 5 ciclos e o programa é fechado depois que o Thread_1 terminou sua execução. Vamos ver o que acontece se removermos a função pthread_join (). Compilar e executar o seguinte código:

Como podemos ver na figura, o loop "para" de Thread_1 não pôde concluir uma passagem antes que a função principal () seja totalmente executada e o programa seja encerrado.

Como usar a função pthread_join () para aguardar um thread múltiplo para concluir a execução no idioma c

Neste exemplo, mostraremos como usar a função pthread_join () para aguardar vários threads simultâneos para concluir.

Para fazer isso, usamos o código do exemplo anterior e adicionamos um segundo thread que é Thread_2 e uma segunda rotina que é Thread_f_2 () que é executada em paralelo com Thread_1. O tempo de execução desta rotina é duas vezes mais que o de Thread_f_1 (), que leva 10 segundos.

O método que usamos é criar os dois threads um após o outro usando a função pthread_create (). Em seguida, primeiro chamamos a função pthread_join () com o fio mais curto em execução, seguido de uma nova chamada para esta função com o tópico mais longo em execução. A seguir, o código completo para este exemplo:

#incluir
#incluir
#incluir
#incluir
void* thread_f_1 (void* n);
void* thread_f_2 (void* n);
int main ()

pthread_t thread_1;
pthread_t thread_2;
pthread_create (& thread_1, null, thread_f_1, null);
pthread_create (& thread_2, null, thread_f_2, null);
pthread_join (thread_1, nulo);
pthread_join (thread_2, nulo);
retornar 0;

void* thread_f_1 (void* n)

para (int a = 5; a!= 0; a--)

printf ("segundos até o final do thread 1: %i \ n", a);
sono (1);

printf ("Fim do thread 1 \ n");
pthread_exit (n);

void* thread_f_2 (void* n)

para (int a = 10; a!= 0; a--)

printf ("segundos até o final do thread 2: %i \ n", a);
sono (1);

printf ("Fim do thread 2 \ n");
pthread_exit (n);

Como vemos na imagem a seguir, ambos os threads concluíram sua execução:

Erros que a função pthread_join () pode retornar: o que são e como eles podem ser detectados?

Quando ocorre um erro, a função pthread_join () retorna um dos seguintes códigos predefinidos:

ESRCH: O identificador especificado não está associado a nenhum tópico.

Einval: O tópico não é junho ou outro tópico já está esperando para se juntar a este.

Edeadlk: Um acidente é detectado.

Esses erros são predefinidos no “errno.Cabeçalho H ”e são devolvidos como resultado no número inteiro de saída da função pthread_join (), não na variável global errno.

A seguir, é apresentado o código do exemplo anterior em que adicionamos uma condição "se" para determinar se ocorreu um erro. Nesse caso, o programa entra em uma condição de interruptor que identifica o erro e exibe uma mensagem no console de comando com a descrição específica desse erro.

Também incluímos o “errno.H ”Cabeçalho e declare a variável de erro que será as condições“ se ”e“ alternar ”.

Para gerar o erro, nos referimos ao Thread_2 no argumento de entrada do thread da função pthread_join () que não é criada.

#incluir
#incluir
#incluir
#incluir
#incluir
void* thread_f (void* n);
int main ()
em terror;
pthread_t thread_1;
pthread_t thread_2;
pthread_create (& thread_1, null, thread_f, null);
error = pthread_join (thread_2, nulo);
if (erro!= 0)
switch (erro)
Case Esrch:
printf ("O identificador não está associado a nenhum thread \ n");
quebrar;
Caso EInval:
printf ("Thread não juntável ou outro thread já está esperando \ n");
quebrar;
Case Edeadlk:
printf ("Um acidente foi detectado.\ n ");
quebrar;

retornar 0;

void* thread_f (void* n)

para (int a = 5; a!= 0; a--)

printf ("segundos até o final do thread: %i \ n", a);
sono (1);

printf ("End of Thread \ n");
pthread_exit (n);

A imagem a seguir mostra a compilação e execução deste código. Veja como o programa entra na instrução "If" e na instância do ESRCH da instrução Switch, que indica que o identificador Thread_2 aponta para um thread inexistente. Você também pode ver que a execução de Thread_1 está incompleta.

Conclusão

Neste artigo do Linux Dint, mostramos como implementar a função Pthread_join () da biblioteca de threads para garantir uma execução completa de um subprocesso.

Explicamos a sintaxe desta função e descrevemos cada um de seus argumentos de entrada e como obter os dados que devem ser passados ​​neles. Em seguida, implementamos a função em um exemplo prático com trechos e imagens de código para mostrar como você pode usar a função pthread_join () para garantir uma execução completa e confiável de um thread.

Também mostramos como vincular corretamente a biblioteca de threads para compilação sem erros. Em uma seção especial, mostramos como detectar e identificar os erros que a função pthread_join () pode gerar.