Utilizzare la libreria di thread C11 in C

Jinku Hu 12 ottobre 2023
  1. Usa la funzione thrd_create per creare un nuovo thread ed eseguire la routine data in C
  2. Usa la funzione thrd_join per attendere il thread specificato in C
Utilizzare la libreria di thread C11 in C

Questo articolo spiegherà diversi metodi su come utilizzare la libreria di thread C11 in C.

Usa la funzione thrd_create per creare un nuovo thread ed eseguire la routine data in C

Il supporto del threading era atteso da tempo nelle specifiche del linguaggio C standard ed è stato finalmente realizzato in C11. Prima di allora, l’API dei thread POSIX veniva utilizzata come strumento principale per utilizzare la programmazione multi-thread. Poiché il C11 ha fornito un’interfaccia più standard che potrebbe essere utilizzata senza dipendenze dalla piattaforma, è stato consigliato di utilizzare l’API del linguaggio ISO rispetto alla versione POSIX. Sebbene le due API non corrispondano nei loro prototipi di funzioni, le caratteristiche principali sono per lo più simili. Nell’esempio seguente, mostriamo il semplice scenario in cui vengono avviati quattro thread per eseguire la funzione printHello e quindi terminati senza unirsi al thread principale.

thrd_create accetta tre argomenti,

  1. Il primo è un puntatore all’identificatore del thread.
  2. Il secondo argomento è di tipo - thrd_start_t, che è semplicemente typedef per un prototipo di puntatore a funzione.
  3. Il terzo parametro specifica un argomento che può essere passato alla funzione.

I codici di stato di ritorno di thrd_create sono definiti utilizzando i valori enum: thrd_success, thrd_nomem e thrd_error.

#include <stdio.h>
#include <stdlib.h>
#include <threads.h>
#include <unistd.h>

#ifndef NUM_THREADS
#define NUM_THREADS 4
#endif

void *printHello(void *thr_id) {
  long tid;
  tid = (long)thr_id;
  printf("Hello There! thread #%ld, pthread ID - %lu\n", tid, thrd_current());
  thrd_exit(EXIT_SUCCESS);
}

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

  for (t = 0; t < NUM_THREADS; t++) {
    rc = thrd_create(&threads[t], (thrd_start_t)printHello, (void *)t);
    if (rc == thrd_error) {
      printf("ERORR; thrd_create() call failed\n");
      exit(EXIT_FAILURE);
    }
  }
  thrd_exit(EXIT_SUCCESS);
}

Produzione:

Hello There! thread 0, pthread ID - 140215498864384
Hello There! thread 1, pthread ID - 140215490471680
Hello There! thread 3, pthread ID - 140215473686272
Hello There! thread 2, pthread ID - 140215482078976

Usa la funzione thrd_join per attendere il thread specificato in C

thrd_join è un analogo della funzione pthread_join e blocca il thread corrente finché il thread specificato non termina l’esecuzione. Richiede due argomenti: l’identificatore del thread e il puntatore int che denotano la posizione in cui il codice di stato di ritorno può essere memorizzato opzionalmente se l’utente fornisce l’indirizzo valido. Se thrd_join viene chiamato su un thread che era già stato scollegato o unito, il risultato è un comportamento indefinito. La funzione restituisce i valori corrispondenti a thrd_success o thrd_error.

Il codice di esempio successivo implementa lo scenario in cui quattro thread incrementano la variabile di tipo atomic_int. Infine, il thread principale che attende che gli altri finiscano stampa il valore della somma finale di counter.

#include <stdatomic.h>
#include <stdio.h>
#include <stdlib.h>
#include <threads.h>
#include <unistd.h>

#ifndef NUM_THREADS
#define NUM_THREADS 4
#endif

atomic_int counter = 0;

enum { MAX_ITER = 1000 };

void *printHello(void *thr_id) {
  long tid;
  tid = (long)thr_id;
  printf("thread %ld started incrementing ID - %lu\n", tid, thrd_current());

  for (int i = 0; i < MAX_ITER; ++i) {
    counter += 1;
  }

  return NULL;
}

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

  for (t = 0; t < NUM_THREADS; t++) {
    rc = thrd_create(&threads[t], (thrd_start_t)printHello, (void *)t);
    if (rc == thrd_error) {
      printf("ERORR; thrd_create() call failed\n");
      exit(EXIT_FAILURE);
    }
  }

  for (t = 0; t < NUM_THREADS; t++) {
    thrd_join(threads[t], NULL);
  }
  printf("count = %d\n", counter);

  thrd_exit(EXIT_SUCCESS);
}

Produzione:

thread 0 started incrementing ID - 139729818216192
thread 2 started incrementing ID - 139729801430784
thread 3 started incrementing ID - 139729793038080
thread 1 started incrementing ID - 139729809823488
count = 4000
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