Utiliser des variables thread_local en C
-
Utilisez le type
_Thread_local
pour déclarer une variable avec la durée de stockage des threads -
Utilisez le type
thread_local
pour déclarer une variable avec la durée de stockage des threads
Cet article explique plusieurs méthodes d’utilisation des variables thread_local
en C.
Utilisez le type _Thread_local
pour déclarer une variable avec la durée de stockage des threads
Le langage C définit plusieurs mots-clés pour différentes classes de stockage comme auto
, static
, register
, extern
. Depuis la spécification du standard C11, le spécificateur _Thread_local
a été ajouté. La durée de stockage _Thread_local
commence au moment de la création du thread et se termine à sa fin. La valeur stockée dans l’objet _Thread_local
est initialisée au démarrage du thread et nettoyée à la fin du thread. En général, les objets thread-locaux sont une autre alternative pour éviter les conditions de concurrence dans les ressources partagées. A savoir, nous séparons implicitement les données entre les threads car les objets qualifiés _Thread_local
ont des instances séparées pour chaque 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);
}
Production:
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
Utilisez le type thread_local
pour déclarer une variable avec la durée de stockage des threads
Alternativement, le langage C définit une expression de macro thread_local
pour désigner le spécificateur comme _Thread_local
. Notez que les variables thread_local
doivent être déclarées dans une portée de fichier pour être visibles par tous les threads, ou l’utilisateur peut également ajouter explicitement un spécificateur static
pour étendre sa portée au niveau du fichier. La structure du programme devra être modifiée car les threads doivent communiquer les valeurs des objets thread_local
au thread principal. L’exemple de code précédent qui implémente le programme de compteur simple doit être modifié pour renvoyer les valeurs de compteur incrémentées au thread appelant. Ainsi, nous devons utiliser la fonction thrd_join
et son deuxième argument qui stocke la valeur de retour de la routine du thread. N’oubliez pas que toutes les valeurs incrémentées doivent être additionnées dans le thread principal, qui est également responsable de l’impression du résultat final dans le 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);
}
Production:
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