public member function
<condition_variable>

std::condition_variable::wait

無條件 (1)
void wait (unique_lock<mutex>& lck);
謂詞 (2)
template <class Predicate>  void wait (unique_lock<mutex>& lck, Predicate pred);
等待通知
當前執行緒(必須已鎖定 lckmutex)的執行將被阻塞,直到它被通知

線上程阻塞時,該函式會自動呼叫 lck.unlock(),允許其他已鎖定的執行緒繼續執行。

一旦被通知(由另一個執行緒顯式呼叫),該函式將解除阻塞並呼叫 lck.lock(),使 lck 保持與呼叫函式時相同的狀態。然後函式返回(請注意,最後這個mutex locking操作可能會在返回前再次阻塞執行緒)。

通常,該函式是由另一個執行緒呼叫成員函式 notify_onenotify_all 來喚醒的。但某些實現可能會產生虛假喚醒,而沒有呼叫這些函式中的任何一個。因此,此函式的使用者應確保其恢復條件得到滿足。

如果指定了 pred (2),則僅當 pred 返回 false 時,函式才會阻塞,並且通知只有在 pred 變為 true 時才能解除執行緒阻塞(這對於檢查虛假喚醒特別有用)。此版本 (2) 的行為如同以下方式實現:
1
while (!pred()) wait(lck);

引數

lck
一個 unique_lock 物件,其互斥量物件當前被該執行緒鎖定。
所有對此物件的wait成員函式的併發呼叫都必須使用相同的底層互斥量物件(透過 lck.mutex() 返回)。
pred
一個可呼叫物件或函式,它不接受任何引數,並返回一個可以被評估為 bool 的值。
此函式會反覆呼叫 pred,直到其求值為 true

返回值



示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
// condition_variable::wait (with predicate)
#include <iostream>           // std::cout
#include <thread>             // std::thread, std::this_thread::yield
#include <mutex>              // std::mutex, std::unique_lock
#include <condition_variable> // std::condition_variable

std::mutex mtx;
std::condition_variable cv;

int cargo = 0;
bool shipment_available() {return cargo!=0;}

void consume (int n) {
  for (int i=0; i<n; ++i) {
    std::unique_lock<std::mutex> lck(mtx);
    cv.wait(lck,shipment_available);
    // consume:
    std::cout << cargo << '\n';
    cargo=0;
  }
}

int main ()
{
  std::thread consumer_thread (consume,10);

  // produce 10 items when needed:
  for (int i=0; i<10; ++i) {
    while (shipment_available()) std::this_thread::yield();
    std::unique_lock<std::mutex> lck(mtx);
    cargo = i+1;
    cv.notify_one();
  }

  consumer_thread.join();

  return 0;
}

輸出

1
2
3
4
5
6
7
8
9
10


資料競爭

該函式執行三個原子操作:
  • lck 的初始解鎖和同時進入等待狀態。
  • 解除等待狀態。
  • 在返回前鎖定 lck
物件上的原子操作根據單一的總順序進行排序,其中此函式中的三個原子操作以與上述相同的相對順序發生。

異常安全

如果任何引數的值對此函式無效(例如,如果 lck互斥鎖物件未被呼叫執行緒鎖定),則會導致未定義行為

否則,如果丟擲異常,則 condition_variable 物件和引數都處於有效狀態(基本保證)。此外,在異常情況下,會嘗試在退出函式作用域前恢復 lck 的狀態(透過呼叫 lck.lock())。

在失敗時,它可能會丟擲 system_error(將來自相應 lockunlock 呼叫的任何錯誤條件傳遞)。
謂詞版本 (2) 也可能丟擲由 pred 丟擲的異常。
否則
無條件版本 (1) 永遠不會丟擲異常(無異常保證)。
謂詞版本 (2) 可能會丟擲由 pred 丟擲的異常,使 condition_variable 物件和引數都處於有效狀態(基本保證)。

如果函式在某個時刻未能恢復鎖定並返回(例如,如果嘗試鎖定或解鎖時丟擲異常),則會呼叫 std::terminate

另見