pthreads
Race conditie in pthreads
Zoeken…
Invoering
Voorbeeld: Overweeg twee threads T1 en T2.
Hoe detecteer je ze?
Als dezelfde variabele / resource / geheugenlocatie toegankelijk is via meerdere threads en ten minste van de thread de waarde van de variabele / resource / geheugenlocatie wijzigt, kan Race Condition optreden. Omdat als een thread de waarde van de variabele / resource / geheugenlocatie wijzigt en een andere thread hetzelfde probeert te lezen, deze de bijgewerkte waarde niet krijgt.
Opmerking : Als alle threads alleen de variabele / resource / geheugenlocatie lezen, zal Race Condition niet optreden.
Voorbeeld: programma lijdt aan raceconditie
#include <stdio.h>
#include <pthread.h>
int x= 0;
void* fun(void* in)
{
int i;
for ( i = 0; i < 10000000; i++ )
{
x++;
}
}
int main()
{
pthread_t t1, t2;
printf("Point 1 >> X is: %d\n", x);
pthread_create(&t1, NULL, fun, NULL);
pthread_create(&t2, NULL, fun, NULL);
pthread_join(t1, NULL);
pthread_join(t2, NULL);
printf("Point 2 >> X is: %d\n", x);
return 0;
}
De output op mijn scherm is:
Point 1 >> X is: 0
Point 2 >> X is: 9925047
Je output zal variëren. Maar het zal zeker geen 20.000.000 zijn. Omdat beide threads dezelfde lus uitvoeren en globale variabele int x;
for ( i = 0; i < 10000000; i++ )
{
x++;
}
Dus de uiteindelijke waarde van x in lijn Point 2 >> X is: 9925047 moet 20.000.000 zijn. Maar zo is het niet.
De status van x kan door een andere thread worden gewijzigd gedurende de tijd tussen het lezen van x en het terugschrijven.
Stel dat een thread de waarde x ophaalt, maar deze nog niet heeft opgeslagen. Een andere thread kan ook dezelfde waarde van x ophalen (omdat er nog geen thread is gewijzigd) en dan slaan ze beide dezelfde waarde (x + 1) weer op in x!
Voorbeeld:
Thread 1: leest x, waarde is 7
Thread 1: voeg 1 toe aan x, waarde is nu 8
Thread 2: leest x, waarde is 7
Thread 1: slaat 8 op in x
Thread 2: voegt 1 toe aan x, waarde is nu 8
Thread 2: slaat 8 op in x
Hoe ga je ermee om?
Wedstrijdomstandigheden kunnen worden vermeden door een soort vergrendelingsmechanisme te gebruiken vóór de code die toegang heeft tot de gedeelde bron of wederzijdse uitsluiting.
Het volgende is een aangepast programma:
Voorbeeld: probleem met raceconditie opgelost
#include <stdio.h>
#include <pthread.h>
int x= 0;
//Create mutex
pthread_mutex_t test_mutex;
void* fun(void* in)
{
int i;
for ( i = 0; i < 10000000; i++ )
{
//Lock mutex before going to change variable
pthread_mutex_lock(&test_mutex);
x++;
//Unlock mutex after changing the variable
pthread_mutex_unlock(&test_mutex);
}
}
int main()
{
pthread_t t1, t2;
printf("Point 1 >> X is: %d\n", x);
//Initlize mutex
pthread_mutex_init(&test_mutex, NULL);
pthread_create(&t1, NULL, fun, NULL);
pthread_create(&t2, NULL, fun, NULL);
pthread_join(t1, NULL);
pthread_join(t2, NULL);
//Destroy mutex after use
pthread_mutex_destroy(&test_mutex);
printf("Point 2 >> X is: %d\n", x);
return 0;
}
Hieronder volgt de output:
Point 1 >> X is: 0
Point 2 >> X is: 20000000
Hier komt het antwoord elke keer uit op 20.000.000.
Opmerking : het gewijzigde programma, dat vrij is van fouten in de raceconditie, zal veel tijd kosten om uit te voeren. Omdat er mutex en ontgrendeling is.