pthreads
Состояние гонки в pthreads
Поиск…
Вступление
Пример: рассмотрим два потока T1 и T2.
Как вы их обнаруживаете?
Если одно и то же местоположение переменной / ресурса / памяти доступно для нескольких потоков, и по крайней мере поток изменяет значение места переменной / ресурса / памяти , тогда может возникнуть состояние гонки . Потому что, если поток изменяет значение места переменной / ресурса / памяти, а другой поток пытается прочитать то же самое, то он не получит обновленное значение.
Примечание . Если все потоки просто считывают местоположение переменной / ресурса / памяти, то условие гонки не будет происходить.
Пример: программа страдает от состояния гонки
#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;
}
Выход на моем экране:
Point 1 >> X is: 0
Point 2 >> X is: 9925047
Ваш результат будет отличаться. Но наверняка это не будет 20 000 000. Поскольку оба потока выполняли один и тот же цикл и имели глобальную переменную int x;
for ( i = 0; i < 10000000; i++ )
{
x++;
}
Таким образом, конечное значение x в строке Point 2 >> X is: 9925047 должно быть 20 000 000. Но это не так.
Состояние x может быть изменено другим потоком за время чтения x и когда оно будет записано обратно.
Предположим, что поток получает значение x, но еще не сохранил его. Другой поток также может получить одно и то же значение x (потому что ни один нить не изменил его), а затем они оба сохраняют одно и то же значение (x + 1) обратно в x!
Пример:
Тема 1: читает x, значение равно 7
Тема 1: добавить 1 в x, теперь значение 8
Thread 2: читает x, значение равно 7
Тема 1: хранит 8 в x
Тема 2: добавляет 1 к x, теперь значение 8
Тема 2: сохраняет 8 в x
Как вы справляетесь с ними?
Условия гонки можно избежать, используя механизм блокировки перед кодом, который обращается к общему ресурсу или взаимному исключению.
Ниже приведена измененная программа:
Пример: проблема с расой
#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;
}
Ниже приведен вывод:
Point 1 >> X is: 0
Point 2 >> X is: 20000000
Здесь ответ приходит как 20 000 000 каждый раз.
Примечание . Измененная программа, свободная от ошибки состояния гонки, займет много времени, чтобы выполнить ее. Потому что есть перегрузка на блокировку и разблокирование mutex .