Usar bloqueo mutex en C
Este artículo explicará varios métodos de cómo usar el bloqueo mutex en C.
Utilice el tipo pthread_mutex_t
y la función pthread_mutex_lock
para proteger la sección crítica del código
Los subprocesos comparten espacios de direcciones, lo que implica que las modificaciones a los datos compartidos, como las variables globales, deben sincronizarse; de lo contrario, habrá un comportamiento incorrecto del programa. Tenga en cuenta que el siguiente código crea 4 hilos adicionales con la llamada pthread_create
y pasa func3
como punto de partida de su ejecución. func3
modifica la variable global shared
con una por una en un bucle for
de 10000 iteraciones. Por lo tanto, si los cuatro subprocesos incrementan el valor de shared
en 10000 cada uno, el programa debería generar 40000.
Si ejecuta el siguiente código, el resultado será un entero aleatorio, pero no 40000. Este comportamiento se clasifica generalmente como una condición de carrera, lo que implica que determinados subprocesos acceden a la variable compartida sin consultarse entre sí, es decir, sincronización. Es decir, a menudo cuando su ejecución del bucle
se entrelaza, se alcanza la inconsistencia en los accesos y almacenes de la variable compartida y, finalmente, se produce una suma incorrecta.
La sección de código donde varios subprocesos modifican el mismo objeto en la memoria se denomina sección crítica. En general, la sección crítica debe protegerse con algún tipo de bloqueo que obligaría a otros subprocesos a esperar hasta que el subproceso actual finalice la ejecución y garantice que todos obtengan el valor incrementado correcto. Mutex es uno de los tipos de bloqueo que se puede utilizar para proteger la sección crítica como este bucle for
en func3
.
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#ifndef NUM_THREADS
#define NUM_THREADS 4
#endif
int shared = 0;
void* func3(void* param) {
printf("Incrementing the shared variable...\n");
for (int i = 0; i < 10000; ++i) {
shared += 1;
}
return 0;
}
int main() {
pthread_t threads[NUM_THREADS];
for (int i = 0; i < NUM_THREADS; ++i) {
pthread_create(&threads[i], NULL, func3, NULL);
}
for (int i = 0; i < NUM_THREADS; ++i) {
pthread_join(threads[i], NULL);
}
printf("%d\n", shared);
exit(EXIT_SUCCESS);
}
Producción :
Incrementing the shared variable...
Incrementing the shared variable...
Incrementing the shared variable...
Incrementing the shared variable...
30384
En este caso, utilizaremos la biblioteca de subprocesos POSIX y su tipo integrado pthread_mutex_t
. La variable de tipo pthread_mutex_t
se suele declarar como duración de almacenamiento static
. Mutex debe inicializarse solo una vez antes de usarse. Cuando el mutex se declara como static
, se debe usar la macro PTHREAD_MUTEX_INITIALIZER
para inicializarlo. Una vez que se inicializa el mutex, los subprocesos pueden utilizar las funciones pthread_mutex_lock
y pthread_mutex_unlock
correspondientemente. pthread_mutex_lock
bloquea el objeto mutex pasado como único argumento. Si el mutex ya estaba bloqueado, el subproceso que realiza la llamada se bloquea hasta que el mutex esté disponible. pthread_mutex_unlock
debe llamarse para desbloquear el mutex. Si hay subprocesos esperando en el mismo mutex, la política de programación determina cuál obtiene el bloqueo de objeto. Finalmente, llamamos pthread_join
en cada uno de los cuatro hilos e imprimimos el entero - shared
, que en este caso debería tener el valor correcto almacenado.
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#ifndef NUM_THREADS
#define NUM_THREADS 4
#endif
int shared = 0;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void* func3(void* param) {
pthread_mutex_lock(&mutex);
printf("Incrementing the shared variable...\n");
for (int i = 0; i < 10000; ++i) {
shared += 1;
}
pthread_mutex_unlock(&mutex);
return 0;
}
int main() {
pthread_t threads[NUM_THREADS];
for (int i = 0; i < NUM_THREADS; ++i) {
pthread_create(&threads[i], NULL, func3, NULL);
}
for (int i = 0; i < NUM_THREADS; ++i) {
pthread_join(threads[i], NULL);
}
printf("%d\n", shared);
exit(EXIT_SUCCESS);
}
Producción :
Incrementing the shared variable...
Incrementing the shared variable...
Incrementing the shared variable...
Incrementing the shared variable...
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