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

另见