std::condition_variable_any::notify_one
來自 cppreference.com
< 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
|