Usa Mutex Lock in C
Questo articolo spiegherà diversi metodi su come utilizzare il blocco mutex in C.
Usa il tipo pthread_mutex_t
e la funzione pthread_mutex_lock
per proteggere la sezione critica del codice
I thread condividono gli spazi degli indirizzi, il che implica che le modifiche ai dati condivisi come le variabili globali devono essere sincronizzate; in caso contrario, ci sarà un comportamento del programma non corretto. Nota che il codice seguente crea 4 thread aggiuntivi con la chiamata pthread_create
e passa func3
come punto di partenza della loro esecuzione. func3
modifica la variabile globale shared
con una alla volta in un bucle di 10000 iterazioni for
. Quindi, se i quattro thread incrementano il valore di shared
di 10000 ciascuno, il programma dovrebbe produrre 40000.
Se esegui il codice seguente, il risultato sarà un numero intero casuale, ma non 40000. Questo comportamento è generalmente classificato come una condizione di competizione, il che implica che determinati thread accedono alla variabile condivisa senza consultarsi a vicenda, ad esempio la sincronizzazione. Vale a dire, spesso quando la loro esecuzione del bucle si interlaccia, si raggiunge l’inconsistenza negli accessi e negli archivi della variabile condivisa e, infine, si ottiene una somma errata.
La sezione di codice in cui più thread modificano lo stesso oggetto nella memoria è chiamata sezione critica. In genere, la sezione critica dovrebbe essere protetta con un qualche tipo di blocco che costringerebbe altri thread ad attendere fino a quando il thread corrente termina l’esecuzione e garantisce che tutti ottengano il valore incrementato corretto. Mutex è uno dei tipi di blocco che può essere utilizzato per proteggere la sezione critica come questo cicli for
in 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);
}
Produzione:
Incrementing the shared variable...
Incrementing the shared variable...
Incrementing the shared variable...
Incrementing the shared variable...
30384
In questo caso, utilizzeremo la libreria dei thread POSIX e il suo tipo pthread_mutex_t
incorporato. La variabile di tipo pthread_mutex_t
viene solitamente dichiarata come durata di archiviazione static
. Mutex dovrebbe essere inizializzato solo una volta prima di essere utilizzato. Quando il mutex è dichiarato come static
, si dovrebbe usare la macro PTHREAD_MUTEX_INITIALIZER
per inizializzarlo. Una volta inizializzato il mutex, i thread possono usare le funzioni pthread_mutex_lock
e pthread_mutex_unlock
corrispondentemente. pthread_mutex_lock
blocca l’oggetto mutex passato come unico argomento. Se il mutex era già bloccato, il thread chiamante viene bloccato finché il mutex non diventa disponibile. pthread_mutex_unlock
dovrebbe essere chiamato per sbloccare il mutex. Se ci sono thread in attesa sullo stesso mutex, il criterio di pianificazione determina quale ottiene il blocco dell’oggetto. Infine, chiamiamo pthread_join
su ciascuno dei quattro thread e stampiamo l’intero - shared
, che in questo caso dovrebbe avere il valore corretto memorizzato.
#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);
}
Produzione:
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