Namespaces
Variants

std:: condition_variable

From cppreference.net
Concurrency support library
Threads
(C++11)
(C++20)
this_thread namespace
(C++11)
(C++11)
Cooperative cancellation
Mutual exclusion
Generic lock management
Condition variables
condition_variable
(C++11)
(C++11)
Semaphores
Latches and Barriers
(C++20)
(C++20)
Futures
(C++11)
(C++11)
(C++11)
Safe reclamation
Hazard pointers
Atomic types
(C++11)
(C++20)
Initialization of atomic types
(C++11) (deprecated in C++20)
(C++11) (deprecated in C++20)
Memory ordering
(C++11) (deprecated in C++26)
Free functions for atomic operations
Free functions for atomic flags
Определено в заголовочном файле <condition_variable>
class condition_variable ;
(начиная с C++11)

std::condition_variable — это примитив синхронизации, используемый вместе с std::mutex для блокировки одного или нескольких потоков до тех пор, пока другой поток не изменит общую переменную ( условие ) и не уведомит std::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 на std::condition_variable (атомарно освобождает мьютекс и приостанавливает выполнение потока до тех пор, пока не будет получено уведомление от переменной условия, не истечет таймаут, или не произойдет ложное пробуждение , затем атомарно захватывает мьютекс перед возвратом).
  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 member function)
уничтожает объект
(public member function)
operator=
[deleted]
не копируемый
(public member function)
Уведомление
уведомляет один ожидающий поток
(public member function)
уведомляет все ожидающие потоки
(public member function)
Ожидание
блокирует текущий поток до пробуждения переменной условия
(public member function)
блокирует текущий поток до пробуждения переменной условия или после указанной длительности таймаута
(public member function)
блокирует текущий поток до пробуждения переменной условия или до достижения указанной точки времени
(public member function)
Нативный дескриптор
возвращает нативный дескриптор
(public member function)

Пример

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

#include <condition_variable>
#include <iostream>
#include <mutex>
#include <string>
#include <thread>
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 thread is processing data\n";
    data += " after processing";
    // отправка данных обратно в main()
    processed = true;
    std::cout << "Worker thread signals data processing completed\n";
    // ручная разблокировка выполняется до уведомления, чтобы избежать пробуждения
    // ожидающего потока только для повторной блокировки (см. notify_one для подробностей)
    lk.unlock();
    cv.notify_one();
}
int main()
{
    std::thread worker(worker_thread);
    data = "Example data";
    // отправка данных в рабочий поток
    {
        std::lock_guard lk(m);
        ready = true;
        std::cout << "main() signals data ready for processing\n";
    }
    cv.notify_one();
    // ожидание рабочего потока
    {
        std::unique_lock lk(m);
        cv.wait(lk, []{ return processed; });
    }
    std::cout << "Back in main(), data = " << data << '\n';
    worker.join();
}

Вывод:

main() signals data ready for processing
Worker thread is processing data
Worker thread signals data processing completed
Back in main(), data = Example data after processing

Смотрите также

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