In Mutua_esclusione abbiamo parlato di race condition di mutex.

Consideriamo un esempio base di race condition :

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
 
int counter = 0;
 
void* increment_counter(){
	for(int i=0; i < 1000000; i++){
		counter++;
	}
}
 
 
int main(int argc, char* argv[]){
	pthread_t t1, t2;
	pthread_create(&t1, NULL, &increment_counter, NULL);
	pthread_create(&t2, NULL, &increment_counter, NULL);
	
	pthread_join(t1, NULL);
	pthread_join(t2, NULL);
	
	printf("Counter is %d\n", counter);
	return 0;
}

il programma crea 2 thread che eseguono (in parallelo) l’incremento di 1,000,000 volte il counter, quindi dovrebbe essere alla fine 2,000,000… e invece se lo eseguivamo otteniamo valori diversi. Questo è un classico esempio di race condition sulla variabile counter.

Per risolvere il problema utilizziamo i mutex. Dichiariamo prima una variabile che farà da mutex :

int count = 0;
pthread_mutex_t mutex;

poi la inizializziamo prima di creare i threads, con pthread_mutex_init che prende come parametri :

  • puntatore oggetto mutex utilizzato (mutex)
  • attributi per il mutex utilizzato
pthread_t t1, t2;
pthread_mutex_init(&mutex, NULL);

Ricordiamoci alla fine di “distruggere” il mutex :

pthread_mutex_destroy(&mutex);
printf("Counter is %d\n", counter);

A questo punto siamo liberi di utilizzare il mutex, e lo facciamo in questo caso “attorno” alla variabile critica contestata e al suo incremento :

for(int i=0; i < 1000000; i++){
	pthread_mutex_lock(&mutex); // acquisisci il mutex
	counter++;
	pthread_mutex_unlock(&mutex); // rilascia il mutex
}

In questo modo otteniamo il risultato atteso :