C++标准库中的std::condition_variable是一种线程同步原语,主要用于线程间的通信,尤其是在多线程环境下配合互斥量(std::mutex)实现线程间的条件等待与唤醒功能。wait()函数是condition_variable类的核心成员函数,它使得线程能够在一个条件不满足时进入等待状态,并在条件满足时被唤醒。
以下是std::condition_variable的wait()函数的基本行为概述:
template <class Rep, class Period>
cv_status wait_for(unique_lock<mutex>& lock,
const chrono::duration<Rep, Period>& rel_time);
template <class Clock, class Duration>
cv_status wait_until(unique_lock<mutex>& lock,
constchrono::time_point<Clock, Duration>& abs_time);
void wait(unique_lock<mutex>& lock);
void wait(unique_lock<mutex>& lock, Predicate pred);
其中最常见的形式是最后一个wait(unique_lock<mutex>& lock),它的工作流程大致如下:
- 解锁互斥量:wait()函数首先要求传入一个已锁定的unique_lock实例,这个unique_lock管理着一个互斥量。在调用wait()时,它会自动解锁关联的互斥量,允许其他线程获取该锁并执行临界区代码。
- 线程阻塞:接着,当前线程会被阻塞(即进入等待状态),并从执行序列中移除,直到接收到适当的“通知”信号。
- 条件检查:当其他线程调用notify_one()或notify_all()时,至少有一个等待的线程(对于notify_one()而言是任意一个)将被唤醒。被唤醒的线程重新尝试获取互斥量,如果获取成功,则继续执行。
-
- 对于带有谓词版本的wait(pred),线程在被唤醒后会先检查谓词函数pred,只有当谓词返回true时线程才真正解除阻塞,否则继续等待直至下一次通知。
- 重新锁定:不论是因为条件满足还是超时,当线程恢复执行时,它会重新锁定互斥量,确保线程安全。
注意事项:
- wait()函数的原子性体现在:线程阻塞和互斥量解锁这两个操作作为一个不可分割的操作完成,确保不会出现竞态条件。
- 调用wait()函数时,必须确保互斥量已被正确锁定,否则行为未定义。
- 等待线程可能因为时间超期或其他原因而自行醒来(spurious wakeup),因此通常需要在循环中调用wait(),并与相应的条件判断结合使用。
我创建了知识星球,在这里分享自己的学习所得和生活感悟,欢迎加入,一起学习,交个朋友。下面是新人券,欢迎领取后加入。