Потоки в Linux: использование глобальной переменной по записи
Есть код программы с использованием глобальной переменной по записи. Вопрос заключается в следующем: почему при запуске программы несколько раз и при увеличении числа потоков (NKIDS) получаются различные результаты?
#include <stdlib.h>
#include <unistd.h>
int tot_items = 0;
struct kidrec {
int data ;
pthread_t id ; };
#define NKIDS 50
void *kidfunc(void *p)
{
int *ip = (int *)p;
int tmp, n;
tmp = tot_items;
for (n = 0;n<50000;n++) tot_items = tmp + *ip;
}
int main ( )
{
struct kidrec kids[NKIDS];
int m;
for (m=0; m<NKIDS; ++m)
{
kids[m].data = m+1;
pthread_create (&kids[m].id, NULL, kidfunc, &kids[m].data);
}
for (m=0; m<NKIDS; ++m) pthread_join(kids[m].id, NULL);
printf ("End of Program. Grand Total = %d\n", tot_items);
exit(0);
}```
Ответы (1 шт):
Потоки не запускаются одновременно. Даже если Вам кажется, что это происходит одновременно, один поток уже может прокрутить пару итераций цикла. В результате переменная tot_items уже будет не та, что при старте. Но так как она не прикрыта ни одним примитивом синхронизации, то вообще сложно угадать, что там будет. Там теоретически может быть любой мусор (да, на современной 64 битной оси такое вряд ли будет - в память никто по байту-двум не пишет, но на какой то другой может быть все).
Поэтому, в коде классическая гонка без синхронизации. Код может выдавать разные числа, потому что порядок запуска и выделения потокам кванта времени не детерминировано (пользователь пошевелил мышкой, по сети пришел очередной пакет и ОСь перераспределила потоки чуточку по другому).
Как исправить программу? а никак. Нужно для начала понять, а что именно от нее ожидается, и потом написать правильно.