Планирование потоков / Условия гонки данных - PullRequest
0 голосов
/ 13 октября 2018

В классе мы изучаем темы и условия гонки.По моим оценкам, для приведенного ниже кода должна быть возможность вывести значение 8 или 9, поскольку вполне возможно, что поток 1 прерывается потоком 2 до обновления значения счетчика, но после его увеличения в регистре eax.

int counter = 10;
  void *worker(void *arg) {
  counter--;
  return NULL;
}
int main(int argc, char *argv[]) {
  pthread_t p1, p2;
  pthread_create(&p1, NULL, worker, NULL);
  pthread_create(&p2, NULL, worker, NULL);
  pthread_join(p1, NULL);
  pthread_join(p2, NULL);
  printf("%d\n", counter);
}

Однако, когда я запускаю код, я всегда получаю выходные данные 8. Это механизм компилятора, который нормализует выходные данные, или это возможно только для кода, чтобы вывести 8 (без гонкиусловие создано)?

Ответы [ 3 ]

0 голосов
/ 13 октября 2018

Код определенно имеет состояние гонки.

Я не нахожу удивительным, что вы видите последовательные результаты - запуск потока занимает немного времени, так что есть хороший шанс, что в вашем случаепервый поток завершается до начала второго.

Тем не менее код явно имеет неопределенное поведение, поскольку нет никаких сомнений в том, что в нем есть условие гонки.

0 голосов
/ 13 октября 2018

Определенно есть условие гонки.Причина, по которой вы этого не видите, заключается в том, что приращение происходит так быстро по сравнению со временем, которое требуется для запуска потока, что вполне вероятно, что первый поток будет выполнен до того, как второй поток даже запустится.Вы увидите состояние гонки, если сделаете объем работы достаточно большим, чтобы первый поток все еще работал, когда запускается второй.

пример: изменить рабочую функцию на декремент в цикле

int counter = 1000000000;

void* worker(void *arg) 
{
  for (int i = 0; i < 500000000; ++i)
    --counter;
  return NULL;
}

Поскольку счетчик начинается с 1 миллиарда, и вы запускаете 2 потока, каждый счетчик декремента на 500 миллионов, вы быожидайте, что счетчик будет равен 0, когда вы закончите, если условия гонки не существовали.

0 голосов
/ 13 октября 2018

Мы не можем рассказать об этом, не зная много сложных деталей о вашей платформе, компиляторе, может быть, даже о процессоре.Код теоретически имеет состояние состязания, но его запуск может быть исключительно трудным, а может быть, даже невозможным.

Конечно, если вы модернизируете свой компилятор или ЦП, измените параметры компиляции, обновите ОС или сделаете что-нибудь еще.из-за ряда других вещей, он может начать вести себя по-другому.

Это одна из причин, по которой условия гонки могут быть настолько коварными.Их может быть невозможно вызвать при некоторых условиях, а затем внезапно начать происходить все время, когда в другом месте вносятся какие-то изменения.

...