Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.57/21: Рейтинг темы: голосов - 21, средняя оценка - 4.57
40 / 29 / 11
Регистрация: 21.06.2019
Сообщений: 201
1

Как устроен condition_variable::wait?

14.12.2020, 17:15. Показов 4357. Ответов 5

Author24 — интернет-сервис помощи студентам
Всем привет, изучаю c_v стандартной библиотеки и возник вопрос что происходит когда condition_variable::wait захватывает поток и он не соответствует условию в предикате? Мне казалось что там вечный цикл который и проверяет этот предикат (собственно по нему он и будит поток). Однако такой код не выводит "sleep" более 1 раза для уснувшего потока, вопрос: почему так? Что там происходит если не постоянная проверка предиката в цикле?

C++
1
2
3
4
5
6
7
std::unique_lock<std::mutex> lk(cv_m);
cv.wait(lk, [&q]() {
    console_m.lock();
    std::cerr << std::this_thread::get_id() << " sleep " << std::endl;
    console_m.unlock();
    return !q.empty() || quit;
 });
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
14.12.2020, 17:15
Ответы с готовыми решениями:

Condition_variable - как заставить работать все пробужденные потоки
Здравствуйте, Что-то я на простом примере даже запутался в работе этого Condition_variable: ...

Как устроен std::string
Добрый день! Недавно я задался таким вопросом - есть класс std::string, который подразумевает...

Как устроен любой API?
Например, есть главная программа, которая имеет данные, использует их в алгоритме. Она запущена. Я...

Как устроен вектор (STL) ?
Вот такой вот вопросец возник. Как организовано хранение вектора в памяти? Последовательно...

5
6579 / 4564 / 1843
Регистрация: 07.05.2019
Сообщений: 13,726
14.12.2020, 17:26 2
Цитата Сообщение от HamsterGamer Посмотреть сообщение
Что там происходит если не постоянная проверка предиката в цикле?
condition_variable::wait ждёт, пока другой поток не вызовет condition_variable::notify_all/notify_one

Добавлено через 1 минуту
C++
1
2
3
std::unique_lock<std::mutex> lk(cv_m);
while (q.empty() && !quit)
    cv.wait(lk);
Добавлено через 27 секунд
При вызове cv.wait(lk) поток усыпляется
1
1538 / 458 / 101
Регистрация: 17.05.2015
Сообщений: 1,426
14.12.2020, 17:30 3
Цитата Сообщение от HamsterGamer Посмотреть сообщение
Что там происходит если не постоянная проверка предиката в цикле?
Нет там никаких циклов.

Когда поток спит - он полностью заморожен.
Он не расходует ресурсы машины.
Не грузит процессор.
Его память может быть отдана другим процессам.

Поток будет спать до тех пор, пока его не разбудит ОС.
Система будет поток по особому системному событию.

Так же, в случае с condition_variable могут быть ложные срабатывания.
В этом случае поток "ничайно" просыпается раньше времени.
Затем запускается предикат, и если он возвращает: "ложная тревога!", тогда поток спит дальше.
1
40 / 29 / 11
Регистрация: 21.06.2019
Сообщений: 201
14.12.2020, 17:42  [ТС] 4
oleg-m1973, вопрос был не про это, а про то, что происходит внутри wait, как он проверяет условия предиката?

https://en.cppreference.com/w/... iable/wait - 2 перегрузка.

Я зашел внутрь файла condition_variable и там написано это:
C++
1
2
while (!__p())
      wait(__lock);
Я предположил что лямбда там вызывается пока не будет нарушено условие while - так оно и есть (судя по виду), однако когда я попытался выводить в этом предикате строку "sleep" она вывелась ровно один раз, несмотря на то что основной поток спал. Почему предикат не вызывался заново?

eva2326, хорошо, я подозревал что wait внутри cv::wait - это уже системный вызов. Если так оно и есть - тогда это логично, спасибо за ответ! Получается notify_one тоже взывает к ОС? Следовательно вызывать его довольно дорого? :\
1
6579 / 4564 / 1843
Регистрация: 07.05.2019
Сообщений: 13,726
14.12.2020, 17:50 5
Цитата Сообщение от HamsterGamer Посмотреть сообщение
Я зашел внутрь файла condition_variable и там написано это:
Я тебе вроде это и показал

Добавлено через 4 минуты
Кстати, можно было никуда не заходить, а просто посмотреть описание https://en.cppreference.com/w/... iable/wait
0
Вездепух
Эксперт CЭксперт С++
11696 / 6375 / 1724
Регистрация: 18.10.2014
Сообщений: 16,078
14.12.2020, 19:35 6
Лучший ответ Сообщение было отмечено HamsterGamer как решение

Решение

Цитата Сообщение от HamsterGamer Посмотреть сообщение
Мне казалось что там вечный цикл который и проверяет этот предикат (собственно по нему он и будит поток).
Это какое-то самопротиворечащее утверждение. Если поток спит, то кто же тогда выполняет этот "вечный цикл"? Если поток не спит, то о каком "будит" может идти речь?

Никакого "вечного цикла" (то есть постоянно активного цикла) там нет. Поток полноценно спит, то есть система прекращает его выполнение полностью, то тех пор пока какой-то другой поток не "дернет" этот condition variable. Однако не стоит забывать про возможность spurious wakeup: поток может вдруг ни с того ни с сего проснуться без причины (то есть даже если никто не дергал эту condition variable), проверить предикат и снова лечь спать.

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

Цитата Сообщение от HamsterGamer Посмотреть сообщение
Однако такой код не выводит "sleep" более 1 раза для уснувшего потока, вопрос: почему так?
Так и должно быть. Пока поток "спит" предикат никто не проверяет. Когда поток просыпается, он один раз проверяет предикат, чтобы убедиться, что "пора просыпаться" и просыпается.

Но еще раз, из-за spurious wakeup, если оно вдруг произойдет, теоретически поток может вывести "sleep" более 1 раза. То есть теоретически поток может спать "неспокойным сном": периодически неожиданно просыпаться без причины, проверять предикат, понимать, что это случайное ненужное пробуждение, и снова укладываться спать.

Цитата Сообщение от HamsterGamer Посмотреть сообщение
Что там происходит если не постоянная проверка предиката в цикле?
Читаем литературу на тему того, как устроен системный планировщик задач (task scheduler) и что такое состояние "sleep" для потока.
1
14.12.2020, 19:35
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
14.12.2020, 19:35
Помогаю со студенческими работами здесь

C++11, потоки, std::condition_variable
Проблема в том, что в коде ниже сначала работает лишь поток th1, а затем только th2 (поток th1...

Как устроен const std::vector
Здравствуйте, я хочу задать несколько вопросов, ответы на которые я не смог найти на просторах...

Не понятно как работает пример std::condition_variable::wait
Здравствуйте! Разбираюсь с std::condition_variable и не могу понять пример кода из...

Как устроен QtCreator
кто нибудь знает как устроен QtCreator? объясню что имею ввиду, ставлю QtCreator на armbian( это...

Как устроен таймер?
Для примера, такой код: int a, b, c;...

Как устроен криптор?
Хотелось бы узнать как устроен криптор, кто то в курсе?


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
6
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru