Разница между методами std :: atomi c и std :: condition_variable wait, notify_ * - PullRequest
6 голосов
/ 12 июля 2020

Я просматривал «библиотеку операций Atomi c» и наткнулся на новую функцию С ++ 20 - методы atomi c 'wait' и 'notify_ '. Мне любопытно, в чем разница между методами std :: condition_variable 'wait' и 'notify_ '.

Ответы [ 2 ]

4 голосов
/ 13 июля 2020

Есть разница в отношении всего шаблона использования.

condition_variable ожидание требует блокировки мьютекса. Перед уведомлением следует использовать ту же блокировку мьютекса:

std::mutex mtx;
std::condition_variable cv;

bool condition();
void change_condition();

...

std::unique_lock<std::mutex> lock(mtx);
while (!condition())
{
   cv.wait(lock);
}

...

std::unique_lock<std::mutex> lock(mtx);
change_condition();
lock.unlock();
cv.notify_one();

Теперь, если у вас есть atomi c с условной переменной, вам все равно нужна блокировка:

std::mutex mtx;
std::condition_variable cv;

std::atomic<bool> condition;

...

std::unique_lock<std::mutex> lock(mtx);
while (!condition.load())
{
   cv.wait(lock);
}

...

std::unique_lock<std::mutex> lock(mtx);
condition.store(true);
lock.unlock();
cv.notify_one();

Atomi c by Сам по себе не нуждается в защите с замком, поэтому его можно модифицировать не под замком. Однако блокировка мьютекса по-прежнему необходима для синхронизации с ожиданием и предотвращения потери пробуждения. Альтернативой пробуждению потока является следующее:

condition.store(true);
std::unique_lock<std::mutex> lock(mtx);
lock.unlock();
cv.notify_one();

Блокировка мьютекса не может быть пропущена даже на стороне уведомителя.

(И вам не сойдет с рук condiion_variable_any и «нулевой мьютекс», который ничего не делает в своем lock / unlock).

Теперь, atomi c подожди. Помимо отсутствия ложных пробуждений, упомянутых в другом ответе, мьютекс не требуется:


std::atomic<bool> condition;

...

condition.wait(false);

...

condition.store(true);
condition.notify_one();
4 голосов
/ 12 июля 2020
Методы

std: atomi c wait, notify_all и notify_one аналогичны методам условных переменных. Они позволяют реализовать logi c, которая ранее требовала условной переменной, используя гораздо более эффективные и легкие переменные atomi c.

Функция wait блокирует поток до значения atomi c объект модифицируется. Требуется аргумент для сравнения со значением объекта atomi c. И он неоднократно выполняет:

  • Если значения равны, он блокирует поток до тех пор, пока не будет уведомлен notify_one или notify_all, или поток не будет ложно разблокирован.
  • В противном случае, возвращает.

ПРИМЕЧАНИЕ: wait гарантированно возвращается только в том случае, если значение изменилось, даже если базовая реализация ложно разблокируется.

Вы можете найти реализацию здесь: https://github.com/ogiroux/atomic_wait/.

Стратегия выбирается таким образом, по платформе:

  • Linux: по умолчанию на фьютекс (с таблицей), откат на фьютекс (без таблицы) -> CV -> отсрочка по времени -> вращение.
  • Ma c: по умолчанию для CV (таблица), откат к отсрочке по времени -> вращение .
  • Windows: по умолчанию для фьютекса (без таблицы), откат на отсрочку по времени -> вращение.
  • CUDA: по умолчанию на отсрочку по времени, откат на вращение. (Это не все зарегистрировано в этом дереве.)
  • Неопознанная платформа: вращение по умолчанию.
...