90 likes | 261 Views
Exclusion mutuelle Thread Mutex. l'écriture des programmes multithread nécessite de faire respecter l'accès mutuellement exclusif aux données partagées . Cela se fait avec des objets mutex .
E N D
Exclusion mutuelle Thread Mutex • l'écriture des programmes multithread nécessite de faire respecter l'accès mutuellement exclusif aux données partagées. • Cela se fait avec des objets mutex. • Mutex(anglais : Mutual exclusion, Exclusion mutuelle) est une primitive de synchronisation utilisée en programmation informatique pour éviter que des ressources partagées d'un système ne soient utilisées en même temps • L'idée de base est d'associer un mutex à chaque objet de donné partagé( on parle de zone critique du code) et ensuite exiger que chaque thread qui souhaite utiliser les données partagées de commence par verrouiller le mutex avant de l’utiliser. Procédure • Déclarer un objet de type pthread_mutex_t. • Initialiser l'objet en appelant mutex_pthread_init (). • Appelez pthread_mutex_lock () pour obtenir un accès exclusif à l'objet de données partagée. • Appelez pthread_mutex_unlock () pour libérer l'accès exclusif et de permettre un autre thread d’utiliser l'objet de données partagée. • Débarrassez-vous de l'objet en appelant pthread_mutex destroy ().
Veillez à respecter ces points • Aucun Thread ne doit tenter de verrouiller ou déverrouiller un mutex qui n'a pas été initialisé; • Le thread qui verrouille un mutex doit être le thread qui le déverrouille; • Aucun thread ne doit avoir le mutex verrouillé lorsque vous détruisez le mutex. • Toute mutex initialisé devrait finalement être détruit, mais seulement après que tous threads, qu'il l’utilise, soient arrêtés ou ne sont plus longuement utilisés
#include <pthread.h> #include <unistd.h> #include <stdio.h> pthread_mutex_t lock ; int shared_data ;//variable partagée // Often shared data is more complex than just an int. void *thread_function(void *arg) { int i ; for ( i = 0 ; i < 1024*1024; ++i ) {// Access the shared data here. pthread_mutex_lock(&lock) ; shared_data++; //zone critique qu’il faut protèger de l’accès conccurente pthread_mutex_unlock(&lock) ;} return NULL;} int main ( void) { pthread_t thread_ID ; int i ; void *exit_status; // Initialize the mutex before trying to use it. pthread_mutex_init(&lock, NULL); pthread_create(&thread_ID, NULL, thread_function, NULL); // Try to use the shared data. for ( i=0; i<10; ++i ) { sleep(1); pthread_mutex_lock(&lock ) ; printf ( "\r pour i= %d Shared integer 's value = %d\n" , i,shared_data ) ; pthread_mutex_unlock(&lock);} printf("\n"); pthread_join(thread_ID, &exit_status ) ; // Clean up the mutex when we are finished with it. pthread_mutex_destroy(&lock ) ; return 0 ; }
Exemple • Imaginons qu' un thread écrive dans un tableau d' entiers et qu’un autre thread lise les valeurs de ce tableau .Il est nécessaire de bloquer l' accès au tableau d’entier au thread en lecture jusqu' à ce que le thread en écriture est fini , ainsi on s' assure le thread en lecture ait bien récupéré toutes les valeurs .
#include <stdio.h> #include <stdlib.h> #include <pthread.h> #include <unistd.h> static pthread_mutex_t mon_verrou; /* création du verrou */ volatile int tableau[5]; /* indique que cette variable est partagée , indispensable pour éviter des problèmes d'atomicité */ void *lire_tableau(void *nom_du_thread) {int compteur; pthread_mutex_lock (&mon_verrou); /* on attend de pouvoir ouvrir le verrou , le thread d'écriture est lancé avant la lecture */ //verouiller le tableau for(compteur=0;compteur!=5;compteur++) {printf("lire_tableau, tableau[%d] est égal à %d\n", compteur, tableau[compteur]);} pthread_mutex_unlock (&mon_verrou); /* on rend le verrou */ pthread_exit(0); /* fin execution du thread et renvoie la valeur 0 */ } void *ecrire_tableau(void *nom_du_thread) {int compteur; pthread_mutex_lock (&mon_verrou); /* on verrouille pendant l' écriture */ for(compteur=0;compteur!=5;compteur++) {tableau[compteur] = 5*compteur+3; printf("ecrire_tableau, tableau[%d] est égal à %d\n", compteur, tableau[compteur]); sleep(2); /* ralentissement du thread pour simuler que le thread est plus lent que celui de lecture */ } pthread_mutex_unlock (&mon_verrou); /* on déverrouille */ pthread_exit(0); /* fin execution du thread et renvoie la valeur 0 */ }
int main() { pthread_t thread1, thread2; void *retour_thread; /* initialisation du verrou */ pthread_mutex_init (&mon_verrou, NULL); /* creation du thread d'écriture */ if(pthread_create (&thread1, NULL, ecrire_tableau, NULL) < 0) { fprintf(stderr,"pthread_create : erreur thread ecrire"); exit(1); } /* creation du thread de lecture */ if(pthread_create (&thread2, NULL, lire_tableau, NULL) < 0) { fprintf(stderr,"pthread_create : erreur thread lire"); exit(1); } /* fonctions pour attendre la fin des thread */ (void)pthread_join(thread1,&retour_thread); (void)pthread_join(thread2,&retour_thread); return 0; }