std::condition_variable::notify_one() 不会唤醒等待线程
std::condition_variable::notify_one() does not wake up a waiting thread
我有一个类似于以下内容的代码:
#include <mutex>
#include <condition_variable>
#include <future>
std::mutex mtx;
std::condition_variable cv;
std::future<void> worker;
void worker_thread() {
{
std::lock_guard<std::mutex> lg{ mtx };
// do something 1
}
cv.notify_one();
// do something 2
}
int main() {
{
std::unique_lock<std::mutex> lg{ mtx };
worker = std::async(std::launch::async, worker_thread);
cv.wait(lg);
}
// do something 3
}
主线程没有继续// do something 3
,我不明白为什么。我认为在主线程传递cv.wait(lg)
后,应该从工作线程到达行cv.notify_one()
,因此没有理由挂起。
一些流数据处理,而主线程主要负责 GUI 事件处理。
// do something 1
是关于应该在工作线程内完成的一些初始化。主线程应等待工作线程完成它。
// do something 2
是工作线程的主要工作。
// do something 3
是主线程的主要工作。
将cv.notify_one()
更改为cv.notify_all()
没有帮助。
条件变量的这种用法是否正确?
我必须回溯我原来的答案,我为此向Junekey道歉。我误读了代码,并得出结论,存在竞争条件。我无法重现该问题。我们需要一个实际上永远阻止 cv.wait 的示例,以便弄清楚它为什么要这样做。然而,如果没有其他原因,代码是不正确的,只是因为它可能会在worker_thread调用 cv.notify 之前收到虚假通知并通过 cv.wait。这种情况很少发生,但确实会发生。
此代码或多或少是规范的:
#include <mutex>
#include <condition_variable>
#include <thread>
std::mutex mtx;
std::condition_variable cv;
bool worker_done = false; // <<< puts the "condition" in condition_variable
void worker_thread() {
// do something 1
{
std::lock_guard<std::mutex> lg{ mtx };
worker_done = true; // ... and whatever
}
cv.notify_one();
// do something 2
}
int main() {
std::thread workman(worker_thread);
{
std::unique_lock<std::mutex> lg{ mtx };
while (!worker_done) {
cv.wait(lg);
}
}
// do something 3
workman.join();
}
对不起。这个问题是完全错误的。我认为"通知应该在主线程开始等待后触发"的说法仍然是正确的,但挂起的根本原因是虚假的觉醒,正如 Jive Dadson 和 Erik Alapää 指出的那样。
我无法在没有优化选项的情况下编译代码是有原因的,所以我误解了挂起点,因为调试器指向的点不是很清楚。挂点不是线cv.wait(lg)
.它在// do something 3
里面的某个地方.
我有一个标志,如果成功// do something 1
则设置,而如果在// do something 1
内抛出异常,则会清除该标志。在// do something 3
中,该标志被选中,如果它指示失败,则主线程调用worker.get()
来重新抛出异常。由于// do something 2
是无限循环的一种形式,因此如果主线程被虚假唤醒,则主线程只会挂起cv
,因此尚未设置标志。
现在它工作正常!谢谢大家。
- 为什么我的C#代码在调用回C++COM直到Task时会暂停.等待/线程.加入
- 虚假唤醒是否会解锁所有等待线程,甚至是不相关的线程?
- 视频在唤醒其他线程时输入设备断开连接
- 等待线程的最佳方式是什么
- std::thread从函数启动,无需等待线程完成
- 带有共享缓冲区的两个等待线程(生产者/消费者)
- std::condition_variable::notify_one() 不会唤醒等待线程
- pthread_cond_wait唤醒多线程示例
- Boost::线程 / C++11 std::thread,想要唤醒工作线程的条件
- 在退出进程时等待线程完成
- 如何正确等待线程中的信号
- 如何等待线程直到它开始运行
- 在纯虚拟类的析构函数中等待线程死亡会导致运行时错误
- 更改可报警/可等待线程的上下文
- C++11 std::线程并等待线程完成
- 我如何在Qt中等待线程完成而不阻塞其执行
- Notify_all不唤醒等待线程
- 如何使用boost条件变量来等待线程完成处理
- 等待线程结束(c++)
- std::condition_variable – 通知一次,但等待线程唤醒两次