std::condition_variable_any::notify_one
来自 cppreference.cn
< cpp | thread | condition variable any
void notify_one() noexcept; |
(C++11 起) | |
如果有任何线程正在等待 *this,调用 notify_one
将解除阻塞其中一个等待线程。
目录 |
[编辑] 参数
(无)
[编辑] 返回值
(无)
[编辑] 注意
notify_one()
/notify_all()
的效果以及 wait()
/wait_for()
/wait_until()
的三个原子部分(解锁+等待,唤醒和加锁)的每个效果都在一个总顺序中发生,这个总顺序可以看作是原子变量的修改顺序:这个顺序是针对这个单独的条件变量的。这使得 notify_one()
不可能,例如,被延迟并解除阻塞一个在调用 notify_one()
之后才开始等待的线程。
通知线程不需要持有与等待线程持有的相同互斥锁;事实上,这样做是一种性能上的优化,因为被通知的线程会立即再次阻塞,等待通知线程释放锁。然而,某些实现(特别是许多 pthreads 的实现)会识别这种情况,并通过在通知调用中直接将等待线程从条件变量的队列转移到互斥锁的队列,而无需唤醒它,从而避免这种“赶紧起来然后等待”的情况。
然而,当需要精确调度事件时,在持有锁的情况下进行通知可能是必要的,例如,如果等待线程在条件满足时退出程序,导致通知线程的条件变量被销毁。在互斥锁解锁但通知之前发生虚假唤醒将导致对已销毁对象调用通知。
[编辑] 示例
运行此代码
#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 documentation for cnd_signal
|