是否有其他方法可以使用条件变量捕获可能错过的信号
Are there alternative ways to catch potentially missed signals with condition variables?
考虑以下简化示例:
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
std::mutex mutex;
std::condition_variable cv;
bool cv_flag = false; // I'm talking about this flag here
void startThread1()
{
std::cout << "thread 1 prints firstn";
{
// Set the flag (lock to be safe)
std::unique_lock<std::mutex> lock(mutex);
cv_flag = true;
}
cv.notify_one();
}
void startThread2()
{
std::unique_lock<std::mutex> lock(mutex);
if (!cv_flag)
{
cv.wait(lock);
}
std::cout << "thread 2 prints secondn";
}
int main()
{
std::thread thread1(startThread1);
std::thread thread2(startThread2);
thread1.join();
thread2.join();
}
在这里,cv_flag
用于确保线程 2 不会锁定并wait()
线程 1 是否已发送带有 notify_one()
的通知。如果没有它,线程 2 可能会在线程 1 已经调用 notify_one()
后锁定并wait()
,从而导致无限期挂起,因为线程 2 正在等待已经发生的事情。
我见过很多这样的代码,其中像 cv_flag
这样的东西仅用于检测可能错过的通知。
这真的是唯一的方法吗?最干净、最简单的呢?我认为如果你能做这样的事情,那就太好了:
std::mutex mutex;
std::condition_variable cv;
// no more need for cv_flag
void startThread1()
{
std::cout << "thread 1 prints firstn";
cv.notify_one();
}
void startThread2()
{
std::unique_lock<std::mutex> lock(mutex);
cv.wait_unless_already_notified(lock); // Unfortunately, this function doesn't exist
std::cout << "thread 2 prints secondn";
}
有没有像wait_unless_already_notified()
?如果不存在,是否存在不存在的技术原因?
编辑:将信号/信号引用更改为通知/通知/通知以消除歧义。
条件变量不用于检测信号!条件变量的目的是等到一个或多个线程完成可以检测为尚未完成的操作。该信号仅指示另一个线程已更改某些内容,等待线程应重新评估它正在等待的条件。除了发送到条件变量的信号之外,还需要更改其他内容以等待。如果要检测另一个线程是否刚刚发送了某个信号,则需要另一个线程来设置相应的指示。
请注意,但是,您的代码是有问题的:wait()
不一定会因为发送信号而唤醒。它可以由于虚假唤醒而唤醒,而没有另一个线程发出信号。也就是说,您需要始终使用wait()
来重新评估条件,例如:
-
while (!cv_flag) { cv.wait(lock); }
-
cv.wait(lock, [&](){ return cv_flag; });
cv_flag
仅用于检测可能丢失的信号。
您的信息不完整。该标志的主要功能不仅仅是检测错过的通知(这与信号不同,参见 Dietmar 的评论),而主要是为了防止condition_variable
的虚假唤醒(换句话说,即使没有人调用cv.notify_*()
函数之一,cv.wait()
也可以返回)。说到这里,你的示例代码是错误的:
if (!cv_flag)
{
cv.wait(lock);
}
它应该是一个while
循环:
while (!cv_flag)
{
cv.wait(lock);
}
有没有像
wait_unless_already_signaled()
?如果不存在,是否存在不存在的技术原因?
由于已经提到了可能的虚假唤醒,因此有必要有一个单独的变量来反映"真实"事件的状态,至少是一个布尔标志,以便在condition_variable
被虚假唤醒时可以恢复等待(因此while
循环而不仅仅是if
)。当然,这个要求使你提出的wait_unless_already_signaled()
毫无用处,这就解释了为什么它不存在。
- Qt VTK交互风格的信号到小部件
- 获取日期异步信号安全吗?如果在信号处理程序中使用,它会导致死锁吗
- 如何将点击的信号和插槽添加到qt中的自定义按钮中
- 如何在没有信号的情况下从C++执行QML插槽
- 线程之间的布尔停止信号
- 如何在信号处理程序和普通函数中对全局变量进行互斥读写操作
- 当用户在qtablewidget中输入单元格时,如何获得信号?C++
- 有可能在信号处理程序中设置promise吗
- 代码在我的计算机上运行良好,但是在将其提交给coursera时遇到未知的信号11问题
- 在条件变量中触发错误信号的频率是多少
- 在信号处理程序中捕获C++未处理的异常并恢复应用程序
- 调试和自由执行中的信号处理
- 升压信号2将插槽传递到成员功能以断开连接
- C++函数包装器来捕获某些信号
- 如何在qt中将信号和插槽与另一个对象连接 --解决了
- 中止信号来自 C++ 中的中止(3) (SIGABRT)
- Qt将信号与另一个类方法连接
- C++ 信号和插槽不工作:插槽不响应事件
- 是否有其他方法可以使用条件变量捕获可能错过的信号
- 如何确保来自 QTcpSocket 的 readyRead() 信号不会被错过?