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

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)
(C++11)
(C++11)
Условные переменные
condition_variable
(C++11)
(C++11)
Семафоры
Защёлки и б��рьеры
(C++20)
(C++20)
Фьючерсы
(C++11)
(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)
обеспечивает базовую функциональность взаимного исключения
(класс) [править]
реализует обёртку владения мьютексом строго в области видимости
(шаблон класса) [править]
реализует перемещаемую оболочку владения мьютексом
(шаблон класса) [править]