Защищено ли содержимое предиката в мьютексе метода C++ wait_for или нет?

Предположим, 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;
    }
}
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
6
0
88
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я прав?

Нет, ты ошибаешься.

Я думаю, потому что, когда код доходит до 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)'?

passionateProgrammer 21.11.2022 05:24

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

Sam Varshavchik 25.11.2022 21:41

Другие вопросы по теме