Esiste una "condizione di competizione" quando il codice multithread (o altrimenti parallelo) che accede a una risorsa condivisa potrebbe farlo in modo da causare risultati imprevisti.
Prendi questo esempio:
for ( int i = 0; i < 10000000; i++ )
{
x = x + 1;
}
Se hai 5 thread che eseguono questo codice contemporaneamente, il valore di x NON DOVREBBE finire per essere 50.000.000. Varrebbe infatti ad ogni corsa.
Questo perché, affinché ogni thread aumenti il valore di x, devono fare quanto segue: (semplificato, ovviamente)
Recupera il valore di x
Aggiungi 1 a questo valore
Memorizza questo valore su x
Qualsiasi thread può essere in qualsiasi fase di questo processo in qualsiasi momento e possono calpestarsi quando è coinvolta una risorsa condivisa. Lo stato di x può essere modificato da un altro thread durante il tempo tra x viene letto e quando viene riscritto.
Diciamo che un thread recupera il valore di x, ma non lo ha ancora memorizzato. Un altro thread può anche recuperare lo stesso valore di x (perché nessun thread lo ha ancora modificato) e quindi entrambi memorizzerebbero lo stesso valore (x + 1) in x!
Esempio:
Discussione 1: legge x, il valore è 7
Discussione 1: aggiungi 1 a x, il valore è ora 8
Discussione 2: legge x, il valore è 7
Discussione 1: memorizza 8 in x
Discussione 2: aggiunge 1 a x, il valore è ora 8
Discussione 2: memorizza 8 in x
Le condizioni di gara possono essere evitate impiegando una sorta di meccanismo di blocco prima del codice che accede alla risorsa condivisa:
for ( int i = 0; i < 10000000; i++ )
{
//lock x
x = x + 1;
//unlock x
}
Qui, la risposta esce ogni volta come 50.000.000.
Per ulteriori informazioni sul blocco, cerca: mutex, semaforo, sezione critica, risorsa condivisa.