std::condition_variable::notify_one
void notify_one() noexcept; | (начиная с C++11) |
Если какие-либо потоки ожидают на *this, вызов notify_one разблокирует один из ожидающих потоков.
Параметры
(нет)
Возвращаемое значение
(нет)
Примечания
Эффекты notify_one()/notify_all() и каждой из трёх атомарных частей wait()/wait_for()/wait_until() (разблокировка и ожидание, пробуждение и блокировка) происходят в едином общем порядке, который можно рассматривать как порядок модификации атомарной переменной: этот порядок является индивидуальным для каждой переменной условия. Это исключает возможность того, что notify_one(), например, будет отложен и разблокирует поток, который начал ожидание сразу после вызова notify_one().
Потоку, отправляющему уведомление, не требуется удерживать блокировку того же мьютекса, что и ожидающие потоки; более того, это ухудшает производительность, поскольку уведомлённый поток сразу же снова заблокируется, ожидая освобождения блокировки потоком, отправившим уведомление. Однако некоторые реализации (в частности, многие реализации pthreads) распознают такую ситуацию и избегают сценария «поторопись и жди»: во время вызова notify они перемещают ожидающий поток из очереди переменной условия непосредственно в очередь мьютекса, не пробуждая его.
Тем не менее уведомление под блокировкой может быть необходимо, если требуется точное планирование событий, например, когда ожидающий поток завершил бы программу при выполнении условия, что привело бы к уничтожению переменной условия потока, отправляющего уведомление. Ложное пробуждение после снятия блокировки мьютекса, но до вызова notify, привело бы к вызову notify для уже уничтоженного объекта.
Пример
#include <chrono>
#include <condition_variable>
#include <iostream>
#include <thread>
using namespace std::chrono_literals;
std::condition_variable cv;
std::mutex cv_m;
int i = 0;
bool done = false;
void waits()
{
std::unique_lock<std::mutex> lk(cv_m);
std::cout << "Waiting... \n";
cv.wait(lk, []{ return i == 1; });
std::cout << "...finished waiting; i == " << i << '\n';
done = true;
}
void signals()
{
std::this_thread::sleep_for(200ms);
std::cout << "Notifying falsely...\n";
cv.notify_one(); // waiting thread is notified with i == 0.
// cv.wait wakes up, checks i, and goes back to waiting
std::unique_lock<std::mutex> lk(cv_m);
i = 1;
while (!done)
{
std::cout << "Notifying true change...\n";
lk.unlock();
cv.notify_one(); // waiting thread is notified with i == 1, cv.wait returns
std::this_thread::sleep_for(300ms);
lk.lock();
}
}
int main()
{
std::thread t1(waits), t2(signals);
t1.join();
t2.join();
}
Возможный вывод:
Waiting... Notifying falsely... Notifying true change... ...finished waiting; i == 1
См. также
| уведомляет все ожидающие потоки (открытая функция-член) |
|
Документация по C для cnd_signal |
|
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/cpp/thread/condition_variable/notify_one