Ограждение атомарного потока: Почему существует гонка данных для этой неатомарной переменной? И имеет ли это значение? - PullRequest
0 голосов
/ 09 января 2019

Допустим, у нас есть 2 темы. Один производитель и один потребитель. У нас есть производитель, который производит данные, и потребитель, который использует эти данные. Однако охранник не атомный!

bool isDataReady = false;
int data = 0;

void Producer() {
  data = 42;
  std::atomic_thread_fence(std::memory_order_release);
  isDataReady = true;
}

void Consumer() {
  while(!isDataReady);
  std::atomic_thread_fence(std::memory_order_acquire);
  assert(data == 42);
}

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

Это потому, что запись (транзакция) в isDataReady может быть не завершена до чтения? И даже если это так, действительно ли это проблема?

1 Ответ

0 голосов
/ 09 января 2019

TL; DR

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

немного длиннее

Этот код имеет проблемы из-за нескольких проблем:

  1. При компиляции Consumer компилятор не знает, что isDataReady может измениться в фоновом режиме, поэтому вполне разумно выдать while(!isDataReady) бесконечный цикл или просто ничего (из-за гарантия продвижения вперед , как было отмечено в комментариях).

  2. Если запись и / или чтение в bool не является атомарным (что не имеет место на большинстве платформ, но теоретически возможно), любое из чтений может вызвать получение данных мусора.

  3. Ограничение памяти с помощью std::memory_order_release гарантирует, что изменения, произошедшие в потоке, будут видны после того, как другой поток вызовет выделение с помощью std::memory_order_acquire (по крайней мере, в упрощении). Таким образом, изменение переменной bool может быть невидимым в другом потоке.

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

...