名稱空間
變體
操作

std::condition_variable::wait

來自 cppreference.com
 
 
併發支援庫
執行緒
(C++11)
(C++20)
this_thread 名稱空間
(C++11)
(C++11)
(C++11)
協同取消
互斥
通用鎖管理
(C++11)
(C++11)
(C++11)
(C++11)
(C++11)
條件變數
(C++11)
訊號量
門閂和屏障
(C++20)
(C++20)
期值
(C++11)
(C++11)
(C++11)
(C++11)
安全回收
(C++26)
危險指標
原子型別
(C++11)
(C++20)
原子型別的初始化
(C++11)(C++20 中已棄用)
(C++11)(C++20 中已棄用)
記憶體排序
(C++11)(C++26 中已棄用)
原子操作的自由函式
原子標誌的自由函式
 
 
void wait( std::unique_lock<std::mutex>& lock );
(1) (C++11 起)
template< class Predicate >
void wait( std::unique_lock<std::mutex>& lock, Predicate pred );
(2) (C++11 起)

wait 導致當前執行緒阻塞,直到條件變數被通知,或出現虛假喚醒。可以任選提供 pred 以檢測虛假喚醒。

1) 原子地呼叫 lock.unlock() 並阻塞於 *this
notify_all()notify_one() 被執行時,執行緒將被解除阻塞。它也可能被虛假地解除阻塞。
當解除阻塞時,呼叫 lock.lock()(可能會在該鎖上阻塞),然後返回。
2) 等價於
while (!pred())
    wait(lock);
該過載可用於在等待特定條件變為true時忽略虛假喚醒。

wait 返回後,lock.owns_lock()true,且 lock.mutex() 被呼叫執行緒鎖定。如果這些後置條件無法被滿足[1],則呼叫 std::terminate

如果滿足以下任何條件,則行為是未定義的:

  • lock.owns_lock()false
  • lock.mutex() 未被呼叫執行緒鎖定。
  • 如果其他一些執行緒也在等待 *this,那麼 lock.mutex() 不同於那些執行緒在 *this 上呼叫的等待函式(waitwait_forwait_until)所解鎖的互斥體。
  1. 這可能發生於對互斥體重新加鎖時丟擲異常。

目錄

[編輯] 引數

- 一個必須被呼叫執行緒鎖定的鎖
pred - 用於檢查是否可以完成等待的謂詞
型別要求
-
Predicate 必須滿足函式物件 (FunctionObject) 的要求。
-
pred() 必須是有效表示式,其型別和值類別必須滿足可布林測試 (BooleanTestable) 的要求。

[編輯] 異常

1) 不丟擲任何異常。
2) pred 丟擲的任何異常。

[編輯] 注意

notify_one()/notify_all() 的效果和 wait()/wait_for()/wait_until() 的三個原子部分(解鎖+等待、喚醒、加鎖)中的每一個,都發生於一個單獨的全序中,該順序可被看作一個原子變數的修改順序:此順序是該單獨的條件變數所特有的。這使得 notify_one() 不可能被延遲,然後解除阻塞一個在 notify_one() 呼叫剛作出後開始等待的執行緒。

[編輯] 示例

#include <chrono>
#include <condition_variable>
#include <iostream>
#include <thread>
 
std::condition_variable cv;
std::mutex cv_m; // This mutex is used for three purposes:
                 // 1) to synchronize accesses to i
                 // 2) to synchronize accesses to std::cerr
                 // 3) for the condition variable cv
int i = 0;
 
void waits()
{
    std::unique_lock<std::mutex> lk(cv_m);
    std::cerr << "Waiting... \n";
    cv.wait(lk, []{ return i == 1; });
    std::cerr << "...finished waiting. i == 1\n";
}
 
void signals()
{
    std::this_thread::sleep_for(std::chrono::seconds(1));
    {
        std::lock_guard<std::mutex> lk(cv_m);
        std::cerr << "Notifying...\n";
    }
    cv.notify_all();
 
    std::this_thread::sleep_for(std::chrono::seconds(1));
 
    {
        std::lock_guard<std::mutex> lk(cv_m);
        i = 1;
        std::cerr << "Notifying again...\n";
    }
    cv.notify_all();
}
 
int main()
{
    std::thread t1(waits), t2(waits), t3(waits), t4(signals);
    t1.join(); 
    t2.join(); 
    t3.join();
    t4.join();
}

可能的輸出

Waiting...
Waiting...
Waiting...
Notifying...
Notifying again...
...finished waiting. i == 1
...finished waiting. i == 1
...finished waiting. i == 1

[編輯] 缺陷報告

下列更改行為的缺陷報告追溯地應用於以前出版的 C++ 標準。

缺陷報告 應用於 釋出時的行為 正確的行為
LWG 2114
(P2167R3)
C++11 可轉換為 bool 對於反映實現的期望來說太弱了 要求已加強
LWG 2135 C++11 如果 lock.lock() 丟擲異常,則行為不明確 在這種情況下呼叫 std::terminate

[編輯] 參閱

阻塞當前執行緒,直到條件變數被喚醒或達到指定的超時時長。
(公開成員函式) [編輯]
阻塞當前執行緒,直到條件變數被喚醒或達到指定的時間點。
(公開成員函式) [編輯]
C 語言文件中關於cnd_wait的內容

[編輯] 外部連結

The Old New Thing 文章:Win32 條件變數中的虛假喚醒。