Пространства имён
Варианты
Действия

std::condition_variable

Материал из cppreference.com
< cpp‎ | thread
 
 
Библиотека поддержки конкуренции
Ветви
(C++11)
(C++20)
(C++20)
Пространство имён this_thread
(C++11)
(C++11)
(C++11)
Атомарные типы
(C++11)
(C++20)
Инициализация атомарных типов
(C++11)(устарело в C++20)
(C++11)(устарело в C++20)
(C++11)(устарело в C++20)
Функции освобождения для атомарных операций
Функции освобождения для атомарных флагов
Упорядочивание памяти
Взаимное исключение
Общее управление блокировкой
(C++11)
(C++11)
(C++11)(C++11)(C++11)
(C++11)
(C++11)
Условные переменные
condition_variable
(C++11)
(C++11)
Семафоры
Защёлки и барьеры
(C++20)
(C++20)
Фьючерсы
(C++11)
(C++11)
(C++11)
 
 
Определено в заголовочном файле <condition_variable>
class condition_variable;
(начиная с C++11)

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

Поток, который намеревается изменить общую переменную, должен

  1. получить std::mutex (обычно через std::lock_guard)
  2. выполнить модификацию, пока блокировка удерживается
  3. выполнить notify_one или notify_all для std::condition_variable (блокировку не требуется удерживать для уведомления)

Даже если общая переменная является атомарной, она должна быть изменена в мьютексе, чтобы правильно опубликовать изменение в ожидающем потоке.

Любой поток, который намеревается ожидать std::condition_variable, должен

  1. получить std::unique_lock<std::mutex> на том же мьютексе, который используется для защиты общей переменной
  2. либо
  1. проверить состояние, если оно уже было обновлено и уведомлено
  2. выполнить wait, wait_for или wait_until. Операции ожидания атомарно освобождают мьютекс и приостанавливают выполнение потока.
  3. Когда условная переменная уведомляется, истекает тайм-аут или происходит ложное пробуждение, поток пробуждается, и мьютекс повторно запрашивается атомарно. Затем поток должен проверить условие и возобновить ожидание, если пробуждение было ложным.
или
  1. используйте предикативную перегрузку wait, wait_for и wait_until, которая заботится о трёх шагах, описанных выше

std::condition_variable работает только с std::unique_lock<std::mutex>; это ограничение позволяет добиться максимальной эффективности на некоторых платформах. std::condition_variable_any предоставляет условную переменную, которая работает с любым объектом BasicLockable, например std::shared_lock.

Условные переменные разрешают одновременный вызов функций-элементов wait, wait_for, wait_until, notify_one и notify_all.

Класс std::condition_variable это StandardLayoutType. Он не является CopyConstructible, MoveConstructible, CopyAssignable или MoveAssignable.

Содержание

[править]Типы-элементы

Тип-элемент Определение
native_handle_typeопределено реализацией

[править]Функции-элементы

создаёт объект
(public функция-элемент)[править]
разрушает объект
(public функция-элемент)[править]
operator=
[удалено]
без копирования присваиванием
(public функция-элемент)[править]
Уведомление
уведомляет один ожидающий поток
(public функция-элемент)[править]
уведомляет все ожидающие потоки
(public функция-элемент)[править]
Одидание
блокирует текущий поток до тех пор, пока условная переменная не будет активирована
(public функция-элемент)[править]
блокирует текущий поток до тех пор, пока условная переменная не будет активирована или по истечении указанного времени ожидания
(public функция-элемент)[править]
блокирует текущий поток до тех пор, пока условная переменная не будет активирована или пока не будет достигнут указанный момент времени
(public функция-элемент)[править]
Встроенный дескриптор
возвращается системный дескриптор
(public функция-элемент)[править]

[править]Пример

condition_variable используется в сочетании с std::mutex для облегчения взаимодействия между потоками.

#include <iostream>#include <string>#include <thread>#include <mutex>#include <condition_variable>   std::mutex m; std::condition_variable cv;std::string data;bool ready =false;bool processed =false;   void worker_thread(){// Ждёт, пока main() отправит данныеstd::unique_lock lk(m); cv.wait(lk, []{return ready;});   // после ожидания мы владеем блокировкой.std::cout<<"Поток worker обрабатывает данные\n"; data +=" после обработки";   // Отправляет данные обратно в main() processed =true;std::cout<<"Поток worker сигнализирует о завершении обработки данных\n";   // Ручная разблокировка выполняется перед уведомлением, чтобы не разбудить// ожидающий поток только для повторной блокировки (подробности смотрите в notify_one) lk.unlock(); cv.notify_one();}   int main(){std::thread worker(worker_thread);   data ="Пример данных";// отправляет данные в поток worker{std::lock_guard lk(m); ready =true;std::cout<<"main() сигнализирует о готовности данных к обработке\n";} cv.notify_one();   // ожидание worker{std::unique_lock lk(m); cv.wait(lk, []{return processed;});}std::cout<<"Возвращение в main(), data = "<< data <<'\n';   worker.join();}

Вывод:

main() сигнализирует о готовности данных к обработке Поток worker обрабатывает данные Поток worker сигнализирует о завершении обработки данных Возвращение в main(), data = Пример данных после обработки

[править]Смотрите также

предоставляет условную переменную, связанную с любым типом блокировки
(класс)[править]
(C++11)
обеспечивает базовую функциональность взаимного исключения
(класс)[править]
(C++11)
реализует обёртку владения мьютексом строго в области видимости
(шаблон класса)[править]
реализует перемещаемую оболочку владения мьютексом
(шаблон класса)[править]
close