Usar variables thread_local en C
-
Utilice el tipo
_Thread_local
para declarar variable con duración de almacenamiento de subprocesos -
Utilice el tipo
thread_local
para declarar variable con duración de almacenamiento de subprocesos
Este artículo explicará varios métodos de cómo utilizar variables thread_local
en C.
Utilice el tipo _Thread_local
para declarar variable con duración de almacenamiento de subprocesos
El lenguaje C define múltiples palabras clave para diferentes clases de almacenamiento como auto
, static
, register
, extern
. Desde la especificación del estándar C11, se agregó el especificador _Thread_local
. La duración del almacenamiento de _Thread_local
comienza en el momento de la creación del hilo y finaliza con su terminación. El valor almacenado en el objeto _Thread_local
se inicializa cuando se inicia el hilo y se limpia cuando termina el hilo. En general, los objetos locales de subprocesos son otra alternativa para evitar condiciones de carrera en recursos compartidos. Es decir, separamos implícitamente los datos entre subprocesos ya que los objetos calificados _Thread_local
tienen instancias separadas para cada subproceso.
#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);
}
Producción :
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
Utilice el tipo thread_local
para declarar variable con duración de almacenamiento de subprocesos
Alternativamente, el lenguaje C define una expresión macro thread_local
para denotar el especificador como _Thread_local
. Tenga en cuenta que las variables thread_local
deben declararse en un alcance de archivo para que sean visibles para todos los subprocesos, o el usuario puede agregar explícitamente un especificador static
también para expandir su alcance al nivel de archivo. La estructura del programa deberá modificarse, ya que los subprocesos deben comunicar los valores de los objetos thread_local
al subproceso principal. El código de ejemplo anterior que implementa el programa de contador simple debe modificarse para pasar los valores de contador incrementados de nuevo al hilo de llamada. Por lo tanto, necesitamos utilizar la función thrd_join
y su segundo argumento que almacena el valor de retorno de la rutina del hilo. Tenga en cuenta que todos los valores incrementados deben sumarse en el hilo principal, que también es responsable de imprimir el resultado final en el 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);
}
Producción :
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