Получить-освободить порядок памяти между несколькими потоками - PullRequest
1 голос
/ 24 сентября 2019

Код:

std::atomic<int> done = 0;
int a = 10;

void f1() {
  a = 20;
  done.store(1, std::memory_order_release);
}

void f2() {
  if(done.load(std::memory_order_acquired) == 1) {
    assert(a == 20);
  }
}

void f3() {
  if(done.load(std::memory_order_acquired) == 1) {
    assert(a == 20);
  }
}

int main() {
  std::thread t1(f1);
  std::thread t2(f2);
  std::thread t3(f3);
  t1.join();
  t2.join();
  t3.join();
}

Вопрос в том, видят ли оба потока 2 и 3 done == 1, будет ли утверждение a == 20 сохраняться в обоих потоках?Я знаю, что приобретение-релиз работает для пары потоков.Но работает ли он также в нескольких потоках?

Ответы [ 2 ]

2 голосов
/ 26 сентября 2019

Да.Отношение релиз-получение выполняется отдельно для всех пар потоков (которые обращаются к одному и тому же атомному расположению!) И гарантирует, что все записи (которые появляются в порядке программы) до того, как релиз будут видимы все читает (которые появляются в программном порядке) после того, как происходит соответствующее приобретение.

1 голос
/ 28 сентября 2019

Релиз - это как публикация газеты (без определенной периодичности), а приобретение - как покупка более позднего издания прямо сейчас, а затем выяснение того, что в нем написано (не заботясь о том, какое это издание или какой сегодня день).(Вам редко нужно создавать версии для этих общих атомов, хотя иногда это может понадобиться.)

Газету может купить любое количество людей.Важно то, что то, что было напечатано, было правдой, когда оно было напечатано, и все еще верно, если они являются инвариантными истинами, такими как создание памятника (неизменного по гипотезе).

Таким образом, операция освобождения публикует то, что верно приВремя публикации и надлежащий дизайн гарантируют, что эти факты не могли измениться, когда вы можете «купить» (приобрести) публикацию.Любое количество потоков может видеть эти факты.

...