Usa la funzione pthread_join in C

Jinku Hu 12 ottobre 2023
  1. Usa la funzione pthread_join per attendere la fine del thread
  2. Usa il valore di ritorno della funzione pthread_join per verificare la presenza di errori
Usa la funzione pthread_join in C

Questo articolo spiegherà diversi metodi su come utilizzare la funzione pthread_join in C.

Usa la funzione pthread_join per attendere la fine del thread

Un programma crea thread con la funzione pthread_create e di solito attende che terminino con la funzione pthread_join. pthread_join richiede solo due argomenti: thread id per specificare il thread atteso e puntatore a void* dove può essere memorizzato lo stato di uscita del thread specificato. Se l’utente non vuole recuperare il codice di uscita del thread atteso, il valore NULL dovrebbe essere passato come secondo argomento. Nell’esempio seguente, mostriamo il programma che crea 8 thread ed esegue la funzione printHello in ognuno di essi. Quindi, il thread chiamante attende ogni thread con la chiamata pthread_join nel bucle. Si noti che memorizziamo anche il codice di stato di uscita dei thread nella variabile retval e stampiamo il suo valore eseguendo il cast a int. Attenzione però, se il thread viene cancellato, il valore PTHREAD_CANCELED viene posto all’indirizzo 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);
}

Produzione:

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

Usa il valore di ritorno della funzione pthread_join per verificare la presenza di errori

La funzione pthread_join restituisce un valore intero che indica anche codici di errore diversi rispetto a una funzione che imposta una variabile globale errno. Il valore restituito è 0 se la chiamata ha avuto successo e questo garantisce che il thread specificato sia terminato. Se il numero intero restituito è uguale a EDEADLK, segnala che è stato rilevato un deadlock. Se viene restituito il valore EINVAL, il thread dato non è unibile e se il valore è uguale a ESRCH, indica che l’ID thread specificato non può essere trovato. In questo caso, implementiamo un’istruzione switch per controllare ogni caso e stampare il messaggio corrispondente su 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);
}

Produzione:

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
Autore: 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

Articolo correlato - C Thread