Предположим, countMe — это глобальная переменная и я запускаю одновременно 10 потоков в этот цикл while, защищена ли переменная countMe мьютексом в предикате? Я думаю, потому что, когда код достигает wait_for, он разблокируется и освобождает блокировку, переменная countMe не защищена мьютексом. Я прав?
while (true)
{
std::unique_lock<std::mutex> lock(mtx_kill);
cv_kill.wait_for(lock, 500ms, [&]() {++countMe; return killFlag; });
if (killFlag)
{
break;
}
}
Я прав?
Нет, ты ошибаешься.
Я думаю, потому что, когда код доходит до wait_for, он разблокирует lock, переменная countMe не защищена от мютекста.
Нет, мьютекс находится в заблокированном состоянии, когда вычисляется лямбда. Гарантировано.
cppreference.com описывает версию предиката wait_for с точки зрения wait_until
, , которая описывается следующим образом:
while (!stop_waiting()) {
if (wait_until(lock, timeout_time) == std::cv_status::timeout) {
return stop_waiting();
}
}
Обратите внимание, что начальное состояние мьютекса заблокировано. Предикат, названный здесь «stop_waiting», всегда вызывается, когда мьютекс находится в заблокированном состоянии.
Вы можете думать о wait_for
просто как о wait
без предикатов, с дополнительной проверкой предиката как о дискретном отдельном шаге. После возврата wait
мьютекс снова блокируется, и это происходит до того, как предикат, ваша лямбда, выполнится. Если он голосует против, мьютекс снова атомарно разблокируется вместе с переменной условия, которая снова ожидает.
P.S. Приведенное выше обсуждение предполагает, что к вашему countMe
всегда обращаются в другом месте с одной и той же блокировкой. Это предполагается вашим вопросом, но просто формально отмечено.
Что ж, должно ли быть или не должно быть что-то, что требует полного понимания не только этого потока выполнения, но и логики всех других потоков выполнения, которые здесь не показаны. Это, очевидно, изменит область блокировки. Являются ли результирующие логические изменения такими, какими они должны быть, это то, что вам нужно выяснить.
Спасибо за объяснение. Должно быть что-то вроде 'std::unique_lock<std::mutex> lk(cv_m);' перед этим циклом while, а также должен ли он быть 'cv_m.wait_unitl(lock, timeout_time) == std::cv_status::timeout)'?