std::condition_variable::notify_one
來自 cppreference.com
< cpp | thread | 條件變數 (condition variable)
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 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 文件 for cnd_signal
|