sas*_*alm 25 c++ qt multithreading qdebug
是qDebug()线程安全的?通过线程安全我不仅仅意味着不崩溃,而且如果我qDebug()从不同的线程调用,输出是否可能变得混乱?我用这个代码测试了它,但它看起来并不是这样,但是,我在文档中的任何地方都找不到它们所讨论的内容.
这是我的测试代码:
#include <QtConcurrent>
#include <QApplication>
void print_a() {
for (int ii = 0; ii < 10000; ii++) {
qDebug("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
}
}
void print_b()
{
for (int ii = 0; ii < 10000; ii++) {
qDebug("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb");
}
}
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QtConcurrent::run(print_a);
QtConcurrent::run(print_b);
return a.exec();
}
Run Code Online (Sandbox Code Playgroud)
在任何地方都没有'a'和'b'混合在同一行,但我仍然不确定它是否100%线程安全......
jon*_*nzh 17
以下是我的回答和评论:
如果qDebug()的文档没有提到它是否是线程安全的,我们应该假设它不是.答案可能取决于平台:qDebug()如何在系统级实现(Linux,Windows,...).
而不是更广泛的线程安全问题,我认为你问的是一个更具体的问题:"在多线程应用程序中使用qDebug()会导致交错的输出线吗?" 答案是"是,偶尔." 正如@dmcontador上面的结果所证明的那样.如上面的@quetzalcoatl所解释的那样,当要打印的字符串越来越长时,概率就会增加.
答案不取决于你是使用qDebug("...")还是qDebug()<<"...",因为它们最终都会调用系统级实现代码.
使用原始示例代码生成交错输出线并不容易.所以我创建了一个新的例子,如下所示:
#include <QCoreApplication>
#include <QtConcurrent>
#define MAX_ITERS 10
#define MAX_LEN 10000
void print_a()
{
QString a(MAX_LEN, 'a');
for(int i = 0; i < MAX_ITERS; ++i) {
qDebug().noquote() << a;
}
}
void print_b()
{
QString b(MAX_LEN, 'b');
for(int i = 0; i < MAX_ITERS; ++i) {
qDebug().noquote() << b;
}
}
int main(int argc, char * argv[])
{
QCoreApplication a(argc, argv);
QtConcurrent::run(print_a);
QtConcurrent::run(print_b);
return 0;
}
Run Code Online (Sandbox Code Playgroud)增加MAX_LEN时概率会增加.
thu*_*uga 14
文档说如果函数未标记为线程安全或可重入,则不应在不同的线程中使用它.如果qDebug()它说:Note: This function is thread-safe.
(这个答案已经更新......文档没有声明该函数之前是线程安全的.)
我担心它不是线程安全的.此外,我尝试了你的代码并混合输出.
aaaaaaaaaaaabbbbbaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbabbbbbbbbbbbbbbbbbb
Run Code Online (Sandbox Code Playgroud)
我有同样的运气 qDebug() << "..."
使用mingw48_32编译器在Qt5.2.1中进行了测试.
事实上,QtDebug相关的函数(如qDebug()、qWarning()等)所做的就是调用消息处理程序,消息处理程序可以通过调用qInstallMessageHandler()来设置。所以这取决于你——这个消息处理程序是否是线程安全的。有一个默认实现,它仅将消息打印到 stderr,它不会阻止来自不同线程的混合输出,因此,如果您希望始终为来自不同线程的调试消息、警告和错误提供非混合的逐行输出线程,您应该安装带有某种锁定(例如 QMutex)的自己的处理程序,如下所示:
QMutex messageMutex;
void myMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
QMutexLocker locker(&messageMutex);
[print msg and context somewhere]
}
int main(int argc, char **argv)
{
qInstallMessageHandler(myMessageHandler);
QApplication app(argc, argv);
[...]
}
Run Code Online (Sandbox Code Playgroud)
注意:正如Kuba Ober正确指出的那样,应该谨慎使用(不过就像一般的锁定一样)。例如,如果从 I/O 库内部调用 QtDebug 函数,同时使用相同的 I/O 库输出调试消息,则可能会出现死锁(例如,当 QtDebug 消息处理程序在持有锁的情况下调用 I/O 时,这是可能的)在非递归互斥体上,然后底层 I/O 机器调用一些回调函数,然后该回调函数调用 QtDebug 函数,该函数再次调用相同的处理程序)。