std::condition_variable
Определено в заголовочном файле <condition_variable> | ||
|---|---|---|
class condition_variable; | (с C++11) |
Класс condition_variable — это примитив синхронизации, используемый с std::mutex, для блокирования одной или нескольких нитей до тех пор, пока другая нить не изменит общую переменную (условие) и не уведомит condition_variable.
Нить, которая намеревается изменить общую переменную, должна:
- Получить
std::mutex(обычно черезstd::lock_guard). - Изменить общую переменную, пока блокировка удерживается.
- Вызвать
notify_oneилиnotify_allдляstd::condition_variable(это можно сделать после освобождения блокировки).
Даже если общая переменная является атомной, она должна быть изменена при удерживании мьютекса, чтобы корректно опубликовать изменение для ожидающей нити.
Любая нить, которая намеревается ожидать std::condition_variable должна:
- Получить
std::unique_lock<std::mutex>на мьютексе, используемом для защиты общей переменной. - Выполнить одно из следующих действий:
- Проверить условие, на случай если оно уже было обновлено и уведомлено.
- Вызвать
wait,wait_for, илиwait_untilдляstd::condition_variable(атомарно освобождает мьютекс и приостанавливает выполнение нити до уведомления о переменной условия, истечения таймаута или возникновения ложного пробуждения, затем атомарно получает мьютекс перед возвратом). - Проверить условие и продолжить ожидание, если оно не выполняется.
- Использовать перегруженный предикат для
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=
[удалено] | не поддерживает копирование (публичная функция-член) |
Уведомление |
|
| уведомляет одну ожидающую нить (публичная функция-член) |
|
| уведомляет все ожидающие нити (публичная функция-член) |
|
Ожидание |
|
| блокирует текущую нить до разбуждения переменной условия (публичная функция-член) |
|
| блокирует текущую нить до разбуждения переменной условия или по истечении заданного таймаута (публичная функция-член) |
|
| блокирует текущую нить до разбуждения переменной условия или до достижения заданного момента времени (публичная функция-член) |
|
Нативный дескриптор |
|
| возвращает нативный дескриптор (публичная функция-член) |
|
Пример
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
См. также
|
(C++11) | предоставляет переменную условия, связанную с любым типом блокировки (класс) |
|
(C++11) | предоставляет основные средства взаимного исключения (класс) |
|
(C++11) | реализует оболочку для управления мьютексом, основанную на области видимости (шаблон класса) |
|
(C++11) | реализует оболочку для управления мьютексом, поддерживающую перемещение (шаблон класса) |
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/w/cpp/thread/condition_variable