std::condition_variable_any::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 для уничтоженного объекта.
Пример
#include <chrono>
#include <condition_variable>
#include <iostream>
#include <thread>
using namespace std::chrono_literals;
std::condition_variable_any 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_any/notify_one