Use a função pthread_join em C

Jinku Hu 12 outubro 2023
  1. Use a função pthread_join para aguardar o término do thread
  2. Use o valor de retorno da função pthread_join para verificar se há erros
Use a função pthread_join em C

Este artigo irá explicar vários métodos de como usar a função pthread_join em C.

Use a função pthread_join para aguardar o término do thread

Um programa cria threads com a função pthread_create e, normalmente, espera que terminem com a função pthread_join. pthread_join leva apenas dois argumentos: thread id para especificar o thread esperado e ponteiro para void* onde o status de saída do thread especificado pode ser armazenado. Se o usuário não quiser recuperar o código de saída do encadeamento esperado, o valor NULL deve ser passado como o segundo argumento. No exemplo a seguir, demonstramos o programa que cria 8 threads e executa a função printHello em cada uma delas. Então, o encadeamento de chamada espera por cada encadeamento com a chamada pthread_join no loop. Observe que também armazenamos o código de status de saída de threads na variável retval e imprimimos seu valor convertendo-o em int. Lembre-se, entretanto, se o thread for cancelado, o valor PTHREAD_CANCELED é colocado no endereço retval.

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

#ifndef NUM_THREADS
#define NUM_THREADS 8
#endif

void *printHello(void *threadid) {
  long tid;
  tid = (long)threadid;
  printf("Hello from thread %ld, pthread ID - %lu\n", tid, pthread_self());
  return NULL;
}

int main(int argc, char const *argv[]) {
  pthread_t threads[NUM_THREADS];
  int rc;
  long t;

  for (t = 0; t < NUM_THREADS; t++) {
    rc = pthread_create(&threads[t], NULL, printHello, (void *)t);
    if (rc) {
      printf("ERORR; return code from pthread_create() is %d\n", rc);
      exit(EXIT_FAILURE);
    }
  }

  int ret;
  for (t = 0; t < NUM_THREADS; t++) {
    void *retval;
    ret = pthread_join(threads[t], &retval);
    if (retval == PTHREAD_CANCELED)
      printf("The thread was canceled - ");
    else
      printf("Returned value %d - ", (int)retval);
  }
  pthread_exit(NULL);
}

Resultado:

Hello from thread 0, pthread ID - 140716669929216
Hello from thread 1, pthread ID - 140716661536512
Hello from thread 2, pthread ID - 140716653143808
Hello from thread 3, pthread ID - 140716644751104
Hello from thread 5, pthread ID - 140716627965696
Hello from thread 4, pthread ID - 140716636358400
Hello from thread 6, pthread ID - 140716550387456
Hello from thread 7, pthread ID - 140716541994752

Use o valor de retorno da função pthread_join para verificar se há erros

A função pthread_join retorna um valor inteiro que também indica diferentes códigos de erro em contraste com uma função que define uma variável global errno. O valor de retorno é 0 se a chamada foi bem-sucedida e isso garante que o thread fornecido foi encerrado. Se o número inteiro retornado for igual a EDEADLK, ele relata que um deadlock foi detectado. Se o valor EINVAL for retornado, o encadeamento fornecido não pode ser juntado, e se o valor for igual a ESRCH, isso indica que o ID do encadeamento fornecido não pode ser encontrado. Neste caso, implementamos uma instrução switch para verificar cada caso e imprimir a mensagem correspondente para stdout.

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

#ifndef NUM_THREADS
#define NUM_THREADS 8
#endif

void *printHello(void *threadid) {
  long tid;
  tid = (long)threadid;
  printf("Hello from thread %ld, pthread ID - %lu\n", tid, pthread_self());
  return NULL;
}

int main(int argc, char const *argv[]) {
  pthread_t threads[NUM_THREADS];
  int rc;
  long t;

  for (t = 0; t < NUM_THREADS; t++) {
    rc = pthread_create(&threads[t], NULL, printHello, (void *)t);
    if (rc) {
      printf("ERORR; return code from pthread_create() is %d\n", rc);
      exit(EXIT_FAILURE);
    }
  }

  int ret;
  for (t = 0; t < NUM_THREADS; t++) {
    void *retval;
    ret = pthread_join(threads[t], &retval);
    if (retval == PTHREAD_CANCELED)
      printf("The thread was canceled - ");
    else
      printf("Returned value %d - ", (int)retval);

    switch (ret) {
      case 0:
        printf("The thread joined successfully\n");
        break;
      case EDEADLK:
        printf("Deadlock detected\n");
        break;
      case EINVAL:
        printf("The thread is not joinable\n");
        break;
      case ESRCH:
        printf("No thread with given ID is found\n");
        break;
      default:
        printf("Error occurred when joining the thread\n");
    }
  }
  pthread_exit(NULL);
}

Resultado:

Hello from thread 0, pthread ID - 140082577512192
Hello from thread 1, pthread ID - 140082569119488
Hello from thread 3, pthread ID - 140082552334080
Hello from thread 5, pthread ID - 140082535548672
Hello from thread 6, pthread ID - 140082527155968
Returned value 0 - The thread joined successfully
Hello from thread 4, pthread ID - 140082543941376
Hello from thread 2, pthread ID - 140082560726784
Returned value 0 - The thread joined successfully
Returned value 0 - The thread joined successfully
Returned value 0 - The thread joined successfully
Hello from thread 7, pthread ID - 140082518763264
Returned value 0 - The thread joined successfully
Returned value 0 - The thread joined successfully
Returned value 0 - The thread joined successfully
Returned value 0 - The thread joined successfully
Autor: Jinku Hu
Jinku Hu avatar Jinku Hu avatar

Founder of DelftStack.com. Jinku has worked in the robotics and automotive industries for over 8 years. He sharpened his coding skills when he needed to do the automatic testing, data collection from remote servers and report creation from the endurance test. He is from an electrical/electronics engineering background but has expanded his interest to embedded electronics, embedded programming and front-/back-end programming.

LinkedIn Facebook

Artigo relacionado - C Thread