Utiliser Mutex Lock en C
Cet article explique plusieurs méthodes d’utilisation du verrouillage mutex dans C.
Utilisez le type pthread_mutex_t
et la fonction pthread_mutex_lock
pour protéger la section critique du code
Les threads partagent des espaces d’adressage, ce qui implique que les modifications des données partagées telles que les variables globales doivent être synchronisées; sinon, il y aura un comportement de programme incorrect. Notez que le code suivant crée 4 threads supplémentaires avec l’appel pthread_create
et passe func3
comme point de départ de leur exécution. func3
modifie la variable globale shared
avec une par une dans une boucle for
d’itération de 10000. Ainsi, si les quatre threads incrémentent la valeur de shared
de 10000 chacun, le programme devrait afficher 40000.
Si vous exécutez le code suivant, le résultat sera un entier aléatoire, mais pas 40000. Ce comportement est généralement classé comme une condition de concurrence, ce qui implique que les threads donnés accèdent à la variable partagée sans se consulter, c’est-à-dire la synchronisation. À savoir, souvent lorsque leur exécution de la boucle
s’entrelace, l’incohérence est atteinte dans les accès et les magasins de la variable partagée, et finalement, une somme incorrecte est produite.
La section de code où plusieurs threads modifient le même objet dans la mémoire est appelée une section critique. En règle générale, la section critique doit être protégée par un type de verrou qui forcerait les autres threads à attendre que le thread actuel termine l’exécution et s’assure qu’ils obtiennent tous la valeur incrémentée correcte. Mutex est l’un des types de verrous qui peuvent être utilisés pour protéger la section critique comme cette boucle for
dans 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);
}
Production:
Incrementing the shared variable...
Incrementing the shared variable...
Incrementing the shared variable...
Incrementing the shared variable...
30384
Dans ce cas, nous utiliserons la bibliothèque de threads POSIX et son type intégré pthread_mutex_t
. La variable de type pthread_mutex_t
est généralement déclarée comme durée de stockage static
. Mutex ne doit être initialisé qu’une seule fois avant d’être utilisé. Lorsque le mutex est déclaré comme static
, il faut utiliser la macro PTHREAD_MUTEX_INITIALIZER
pour l’initialiser. Une fois le mutex initialisé, les threads peuvent utiliser les fonctions pthread_mutex_lock
et pthread_mutex_unlock
en conséquence. pthread_mutex_lock
verrouille l’objet mutex passé comme seul argument. Si le mutex était déjà verrouillé, le thread appelant est bloqué jusqu’à ce que le mutex devienne disponible. pthread_mutex_unlock
doit être appelé pour déverrouiller le mutex. S’il y a des threads en attente sur le même mutex, la politique de planification détermine lequel obtient le verrou d’objet. Enfin, nous appelons pthread_join
sur chacun des quatre threads et imprimons l’entier - shared
, qui dans ce cas devrait avoir la valeur correcte stockée.
#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);
}
Production:
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