Контекст:
Во всех примерах, которые я могу видеть об использовании std::condition_variable::wait()
, включая те, которые приходят с cppreference.com , синхронизации никогда не бывает механизм, используемый для защиты оценки предиката от гонок данных.
Например:
std::mutex m;
std::condition_variable cv;
int i = 0;
void waiting_func()
{
std::unique_lock<std::mutex> lk(m);
cv.wait(lk, [](){return i > 0;}); // No lock/unlock around the access of the global and shared variable i.
// ...
}
Вопрос:
Если такой синхронизации нет, даже из авторитетных источников примеров, я думаю, это потому, что в этом нет необходимости. Но мне интересно, почему? Как std::condition_variable::wait()
оценивает предикат так, чтобы он был потокобезопасным?
Мои мысли:
Я предложил две возможности:
- ) Либо, предикат гарантированно оценен атомарно (я никогда такого не читал, поэтому мой вопрос)
- ) Или, когда отправляется сигнал notify , функция
std::condition_variable::wait()
повторно запрашивает мьютекс перед оценкой предиката.
В случае точки 2.) , это может быть безопасно, если поток который изменяет i
(и вызывает std::condition_variable::notify_one()
), блокирует мьютекс m
перед этим.
Например:
void modify_func()
{
{
std::scoped_lock<std::mutex> lk(m); // Acquire the mutex
i += 1; // Modify i
} // Release the mutex
cv.notify_one();
}
Конечно, другая возможность что мое понимание совершенно неверно, и тогда я упустил суть.
В любом случае, я действительно удивлен, что не смог найти никаких подробностей об этом в документации.