unconditional (1) | void wait (unique_lock<mutex>& lck); |
---|---|
predicate (2) | template <class Predicate> void wait (unique_lock<mutex>& lck, Predicate pred); |
wait() 工作机制的总结
1.condition_variable的wait首先会block当前线程,然后进行互斥量的unlock
(因此,一般上使用wait前,会RAII构造互斥量的lock)
2. 注意,block和unlock必须是个原子动作。
3.最后conditon_variable会把当前线程添加如检测等待队列
4.此时当前线程等待...
5.其他线程执行了这个condition_variable的notify
6.先互斥量的lock,然后unblock。(即跳出wait动作)
7.最后unlock(运行期结束或主动调用unlock)
补充:如果wait函数还传入了第二个参数pred,pred参数应当是个bool型的可调用对象。
此时调用wait,会先判断第二个参数的返回值,如果返回false,就会执行wait,否则直接返回;
当被唤醒后再次判断第二个参数的返回值,如果返回false,会再次进入阻塞,否则直接返回;
如此反复。
例子:10消费者,1个生产者
///以下是10个消费者线程,一个生产者线程
std::mutex mtx2;
std::condition_variable _cond2;
int cargo_2 = 0;
struct is_judge2 {
bool operator()() {
return cargo_2;
}
};
struct is_judge2_ext {
int m_i = 0;
is_judge2_ext(int iv) :m_i(iv) {};
bool operator()() {
//std::cout << "cago " << m_i << " " << cargo_2 << std::endl;
return cargo_2 == m_i;
}
};
void consume3(int iIdx)
{
std::unique_lock<std::mutex> lck(mtx2);
if (0) {
_cond2.wait(lck, is_judge2());
}
else {
std::cout << "wait " << iIdx << std::endl;
_cond2.wait(lck, is_judge2_ext(iIdx));
}
std::cout << "exit " << iIdx << std::endl;
cargo_2 = 0;
}
void test_cond3() //接口,同时也作为生产者
{
int CNT = 10;
std::thread _thd[10];
for (int i = 0; i < CNT; i++) {
_thd[i] = std::thread(consume3, i + 1);
}
for (int i = 0; i < CNT; i++) {
int times = 0;
while (cargo_2) {
std::this_thread::yield();
times++;
}
{
std::unique_lock<std::mutex> lck(mtx2);
cargo_2 = 10 - i;
}
std::cout << "\nSC " << cargo_2 << " " << times << std::endl;
//条件变量通知无须持有锁的!!!
_cond2.notify_all();
}
for (auto& _iter: _thd) {
_iter.join();
}
int k = 0;
}