Spec-Zone.ru › C++

std::condition_variable

Определено в заголовочном файле <condition_variable>
class condition_variable;
(с C++11)

Класс condition_variable — это примитив синхронизации, используемый с std::mutex, для блокирования одной или нескольких нитей до тех пор, пока другая нить не изменит общую переменную (условие) и не уведомит 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 определяется реализацией

Функции-члены

(конструктор)
создает объект
(публичная функция-член)
(деструктор)
уничтожает объект
(публичная функция-член)
operator=
[удалено]
не поддерживает копирование
(публичная функция-член)
Уведомление
notify_one
уведомляет одну ожидающую нить
(публичная функция-член)
notify_all
уведомляет все ожидающие нити
(публичная функция-член)
Ожидание
wait
блокирует текущую нить до разбуждения переменной условия
(публичная функция-член)
wait_for
блокирует текущую нить до разбуждения переменной условия или по истечении заданного таймаута
(публичная функция-член)
wait_until
блокирует текущую нить до разбуждения переменной условия или до достижения заданного момента времени
(публичная функция-член)
Нативный дескриптор
native_handle
возвращает нативный дескриптор
(публичная функция-член)

Пример

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()
{
    // Wait until main() sends data
    std::unique_lock lk(m);
    cv.wait(lk, []{ return ready; });
 
    // after the wait, we own the lock.
    std::cout << "Worker thread is processing data\n";
    data += " after processing";
 
    // Send data back to main()
    processed = true;
    std::cout << "Worker thread signals data processing completed\n";
 
    // Manual unlocking is done before notifying, to avoid waking up
    // the waiting thread only to block again (see notify_one for details)
    lk.unlock();
    cv.notify_one();
}
 
int main()
{
    std::thread worker(worker_thread);
 
    data = "Example data";
    // send data to the worker thread
    {
        std::lock_guard lk(m);
        ready = true;
        std::cout << "main() signals data ready for processing\n";
    }
    cv.notify_one();
 
    // wait for the worker
    {
        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

См. также

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

© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/w/cpp/thread/condition_variable

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API