名稱空間
變體
操作

std::condition_variable_any::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++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 中已棄用)
原子操作的自由函式
原子標誌的自由函式
 
 
template< class Lock >
void wait( Lock& lock );
(1) (C++11 起)
template< class Lock, class Predicate >
void wait( Lock& lock, Predicate pred );
(2) (C++11 起)
template< class Lock, class Predicate >
bool wait( Lock& lock, std::stop_token stoken, Predicate pred );
(3) (C++20 起)

wait 使當前執行緒阻塞,直到條件變數被通知或發生虛假喚醒。可以可選地提供 pred 來檢測虛假喚醒。

1) 原子地呼叫 lock.unlock() 並在 *this 上阻塞。
當執行 notify_all()notify_one() 時,執行緒將被解除阻塞。它也可能被虛假喚醒。
當解除阻塞時,呼叫 lock.lock()(可能會在該鎖上阻塞),然後返回。
2,3) 等待特定條件變為真,可用於忽略虛假喚醒。
2) 等價於
while (!pred())
    wait(lock);
3) 在此呼叫期間註冊 *this,以便在 stoken 的關聯停止狀態上發出停止請求時收到通知;它等效於
while (!stoken.stop_requested())
{
    if (pred())
        return true;
    wait(lock);
}
return pred();

wait 返回後,lock 被呼叫執行緒鎖定。如果此後置條件無法滿足[1],則呼叫 std::terminate

  1. 這可能發生於對互斥體重新加鎖時丟擲異常。

目錄

[編輯] 引數

lock - 一個必須被呼叫執行緒鎖定的鎖
stoken - 一個停止令牌,用於註冊中斷
pred - 用於檢查是否可以完成等待的謂詞
型別要求
-
Lock 必須滿足 BasicLockable 的要求。
-
Predicate 必須滿足函式物件 (FunctionObject) 的要求。
-
pred() 必須是有效表示式,其型別和值類別必須滿足 BooleanTestable 要求。

[編輯] 返回值

1,2) (無)
3) 返回呼叫方之前 pred() 的最新結果。

[編輯] 異常

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

[編輯] 注意

過載 (3) 的返回值表示 pred 是否評估為 true,無論是否請求停止。

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_any 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

[編輯] 另請參閱

阻塞當前執行緒,直到條件變數被喚醒或達到指定的超時時長。
(public member function) [編輯]
阻塞當前執行緒,直到條件變數被喚醒或達到指定的時間點。
(public member function) [編輯]
C 文件,關於 cnd_wait

[編輯] 外部連結

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