std::condition_variable
Определён в заголовочном файле <condition_variable> | ||
|---|---|---|
class condition_variable; | (начиная с C++11) |
std::condition_variable — примитив синхронизации, используемый с std::mutex для блокировки одного или нескольких потоков до тех пор, пока другой поток не изменит общую переменную (условие) и не уведомит std::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 является типом со стандартной компоновкой. Он не удовлетворяет требованиям CopyConstructible, MoveConstructible, CopyAssignable или MoveAssignable.
Вложенные типы
| Имя | Определение |
|---|---|
native_handle_type | определяется реализацией |
Функции-члены
| создаёт объект (открытая функция-член) |
|
| уничтожает объект (открытая функция-член) |
|
|
operator=
[удалён] | копирующее присваивание недоступно (открытая функция-член) |
Уведомление |
|
| уведомляет один ожидающий поток (открытая функция-член) |
|
| уведомляет все ожидающие потоки (открытая функция-член) |
|
Ожидание |
|
| блокирует текущий поток до пробуждения переменной условия (открытая функция-член) |
|
| блокирует текущий поток до пробуждения переменной условия или истечения заданного времени ожидания (открытая функция-член) |
|
| блокирует текущий поток до пробуждения переменной условия или достижения указанного момента времени (открытая функция-член) |
|
Нативный дескриптор |
|
| возвращает нативный дескриптор (открытая функция-член) |
|
Пример
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()
{
// 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/cpp/thread/condition_variable