关于 C++ 11 中的 condition_variable. 有一处没想明白。
資深大佬 : V2WT 6
首先根据: The C++ core guideline 的第 42 条中提到:不要在没有条件的情况下等待( Don’t wait without a condition).主要是为了解决:
- 唤醒丢失
- 虚假唤醒
下面是范例代码:
#include <condition_variable> #include <iostream> #include <thread> std::mutex mutex_; std::condition_variable condVar; bool dataReady{false}; void waitingForWork(){ std::cout << "Waiting " << std::endl; std::unique_lock<std::mutex> lck(mutex_); condVar.wait(lck, []{ return dataReady; }); // (4) std::cout << "Running " << std::endl; } void setDataReady(){ { std::lock_guard<std::mutex> lck(mutex_); dataReady = true; } std::cout << "Data prepared" << std::endl; condVar.notify_one(); // (3) } int main(){ std::cout << std::endl; std::thread t1(waitingForWork); // (1) std::thread t2(setDataReady); // (2) t1.join(); t2.join(); std::cout << std::endl; }
这里再贴一下搜到的资料里 condition_variable 的处理逻辑: wait (lck, pred); 其实等价于 while (!pred()) wait(lck);,它的运行机制如下:
- 线程获取 mutex 的锁,然后对 predicate 的结果进行检查: true:线程继续往下执行; false:condVar.wait() 解锁 mutex,然后线程进入等待(阻塞)状态。
- 假如 condVar 已经在等待状态,此时得到通知(不管发送线程发送,还是虚假唤醒): 线程进入非阻塞状态,然后重新获取 mutex 的锁。 线程检查 predicate 的结果: true:线程继续往下执行; false:condVar.wait() 解锁 mutex,然后线程进入等待(阻塞)状态。
这里我的问题是: 假设运行步骤是这样:
- t2 线程(setDataReady)先执行了。这个时候
dataReady = true. 并且notify_one了。 - t1 线程(waitingForWork)里 wait 的 predicate 为 true.直接往下执行了。并不会阻塞在 condVar.wait 的阶段(根据上面的运行机制是这样)。
所以这个时候相当于空白 notify_one了一次。实际上 t1 线程的运行只跟 dataReady有关,而跟 condition_variable 无关了。那么这次的notify_one的信号到底去哪里了呢?
不知道我有没有描述清楚问题。有大佬能解答一下吗?
大佬有話說 (5)