Usa variabili thread_local in C
-
Usa il tipo
_Thread_local
per dichiarare la variabile con la durata dell’archiviazione del thread -
Usa il tipo
thread_local
per dichiarare la variabile con la durata della memorizzazione dei thread
Questo articolo spiegherà diversi metodi su come utilizzare le variabili thread_local
in C.
Usa il tipo _Thread_local
per dichiarare la variabile con la durata dell’archiviazione del thread
Il linguaggio C definisce più parole chiave per diverse classi di archiviazione come auto
, static
, register
, extern
. Dalla specifica dello standard C11, è stato aggiunto l’identificatore _Thread_local
. La durata della memorizzazione di _Thread_local
inizia al momento della creazione del thread e termina con la sua conclusione. Il valore memorizzato nell’oggetto _Thread_local
viene inizializzato all’avvio del thread e ripulito quando il thread termina. In generale, gli oggetti locali del thread sono un’altra alternativa per evitare condizioni di competizione nelle risorse condivise. Vale a dire, separiamo implicitamente i dati tra i thread poiché gli oggetti qualificati _Thread_local
hanno istanze separate per ogni thread.
#include <stdatomic.h>
#include <stdio.h>
#include <stdlib.h>
#include <threads.h>
#ifndef NUM_THREADS
#define NUM_THREADS 4
#endif
_Thread_local int counter = 0;
enum { MAX_ITER = 10000 };
void *incrementCounter(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 (void *)counter;
}
int main(int argc, char const *argv[]) {
thrd_t threads[NUM_THREADS];
int rc, sum = 0;
for (int i = 0; i < NUM_THREADS; ++i) {
rc = thrd_create(&threads[i], (thrd_start_t)incrementCounter, (void *)i);
if (rc == thrd_error) {
printf("ERORR; thrd_create() call failed\n");
exit(EXIT_FAILURE);
}
}
int retval;
for (int i = 0; i < NUM_THREADS; ++i) {
thrd_join(threads[i], &retval);
sum += retval;
}
printf("count = %d\n", sum);
thrd_exit(EXIT_SUCCESS);
}
Produzione:
thread 1 started incrementing ID - 140162648991488
thread 0 started incrementing ID - 140162657384192
thread 2 started incrementing ID - 140162640598784
thread 3 started incrementing ID - 140162632206080
count = 40000
Usa il tipo thread_local
per dichiarare la variabile con la durata della memorizzazione dei thread
In alternativa, il linguaggio C definisce un’espressione macro thread_local
per indicare lo specificatore come _Thread_local
. Nota che le variabili thread_local
dovrebbero essere dichiarate in un ambito di file per essere visibili a tutti i thread, oppure l’utente può aggiungere esplicitamente anche uno specificatore static
per espandere il suo ambito a livello di file. La struttura del programma dovrà essere modificata poiché i thread dovrebbero comunicare i valori degli oggetti thread_local
al thread principale. Il codice di esempio precedente che implementa il programma contatore semplice deve essere modificato per passare i valori del contatore incrementato al thread chiamante. Quindi, dobbiamo utilizzare la funzione thrd_join
e il suo secondo argomento che memorizza il valore restituito dalla routine del thread. Tieni presente che tutti i valori incrementati dovrebbero essere sommati nel thread principale, che è anche responsabile della stampa del risultato finale nello stdout
.
#include <stdatomic.h>
#include <stdio.h>
#include <stdlib.h>
#include <threads.h>
#ifndef NUM_THREADS
#define NUM_THREADS 4
#endif
thread_local int counter = 0;
enum { MAX_ITER = 10000 };
void *incrementCounter(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 (void *)counter;
}
int main(int argc, char const *argv[]) {
thrd_t threads[NUM_THREADS];
int rc, sum = 0;
for (int i = 0; i < NUM_THREADS; ++i) {
rc = thrd_create(&threads[i], (thrd_start_t)incrementCounter, (void *)i);
if (rc == thrd_error) {
printf("ERORR; thrd_create() call failed\n");
exit(EXIT_FAILURE);
}
}
int retval;
for (int i = 0; i < NUM_THREADS; ++i) {
thrd_join(threads[i], &retval);
sum += retval;
}
printf("count = %d\n", sum);
thrd_exit(EXIT_SUCCESS);
}
Produzione:
thread 1 started incrementing ID - 140162648991488
thread 2 started incrementing ID - 140162640598784
thread 0 started incrementing ID - 140162657384192
thread 3 started incrementing ID - 140162632206080
count = 40000
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