QThreads 并行运行吗?

问题描述 投票:0回答:1

我有两个线程正在运行,它们只是打印一条消息。这是一个简单的例子。

这是我的

Header.h

#pragma once

#include <QtCore/QThread>
#include <QtCore/QDebug>

class WorkerOne : public QObject {
    Q_OBJECT
public Q_SLOTS:
    void printFirstMessage() {
        while (1) {
            qDebug() << "<<< Message from the FIRST worker" << QThread::currentThreadId();
        }
    }
};

class WorkerTwo : public QObject {
    Q_OBJECT
public Q_SLOTS:
    void printSecondMessage() {
        while (1) {
            qDebug() << ">>> Message from the SECOND worker" << QThread::currentThreadId();
        }
    }
};

当然,我的主要内容:

#include <QtCore/QCoreApplication>

#include "Header.h"


int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    WorkerOne kek1;
    QThread t1;
    kek1.moveToThread(&t1);
    t1.setObjectName("FIRST THREAD");

    QThread t2;
    WorkerTwo kek2;
    kek2.moveToThread(&t2);
    t2.setObjectName("SECOND THREAD");

    QObject::connect(&t1, &QThread::started, &kek1, &WorkerOne::printFirstMessage);
    QObject::connect(&t2, &QThread::started, &kek2, &WorkerTwo::printSecondMessage);

    t1.start();
    t2.start();

    return a.exec();
}

当我启动应用程序时,我看到它的预期输出: enter image description here

如您所见,线程 id 不同。添加它是为了确保它们在不同的线程上运行。

我在

printFirstMessage
中设置了唯一的一个断点,并在附加到调试器的调试模式下运行应用程序。一旦调试器停止在我的断点处 - 我等待一段时间并按
Continue
,这样我的调试器就会再次停止在同一个断点处。

我期望看到什么?我预计只会看到一个

<<< Message from the FIRST worker
和来自第二个工作人员的大量消息。但我看到了什么?我只看到两条消息:第一条来自第一个工作人员,第二条来自第二个工作人员。

enter image description here

我按了

Continue
很多次,结果或多或少是一样的。这对我来说很奇怪,因为我希望第二个线程正在运行,而第一个线程被调试器停止。

我决定使用

std::thread
来测试它并编写了以下代码:

#include <thread>
#include <iostream>

void foo1() {
    while (true) {
        std::cout << "Function ONE\n";
    }
}

void foo2() {
    while (true) {
        std::cout << "The second function\n";
    }
}

int main() {
    std::thread t1(&foo1);
    std::thread t2(&foo2);

    t1.join();
    t2.join();
}

在第一个函数中设置一个断点,启动应用程序,在断点处停止后,我点击

Continue
并看到控制台包含来自第二个函数的大量消息,并且只有一个来自第一个函数的消息(正是我所期望的使用
QThread
): enter image description here

有人可以解释一下它是如何与

QThread
一起工作的吗?顺便说一句,我使用
QtConcurrent::run
而不是
QThread
进行了测试,结果符合预期:第二个函数正在运行,而第一个函数由于断点而停止。

multithreading qt qthread
1个回答
3
投票

是的,多个

QThread
实例是允许并行运行的。它们是否有效地并行运行取决于您的操作系统并取决于多种因素:

  • 物理(和逻辑)CPU 核心数。在消费类计算机上,这通常不超过 4 或 8。这是可以有效并行运行的最大线程数(包括其他程序的线程和操作系统本身)。核心数量远低于计算机上通常运行的线程数量。如果您的计算机仅包含 1 个核心,您仍然可以使用多个

    QThread
    ,但操作系统调度程序将交替执行这些线程。
    QThread::idealThreadCount
    可用于查询(逻辑)CPU 核心数。

  • 每个线程都有一个

    QThread::Priority
    。操作系统线程调度程序可以使用该值来确定一个线程相对于另一个线程的优先级(或取消优先级)。当 CPU 核心繁忙时,优先级较低的线程可能比优先级较高的线程获得更少的 CPU 时间。

  • 当前正在运行的其他线程(的工作负载)。

调试程序肯定会改变多线程程序的正常执行:

  • 中断和继续线程有一定的开销。与此同时,其他线程可能仍然/已经执行一些操作。
  • 正如 G.M. 所指出的,大多数情况下,当遇到断点时,所有线程都会被中断。其他线程中断的速度没有明确定义。
  • 调试器通常有一个配置选项,允许中断单个线程,而其他线程继续运行,请参阅 f.ex。 这个问题.
  • 当另一个线程被中断/再次启动时执行的循环数量取决于执行单个循环所需的 CPU 指令数量。调用
    qDebug()
    QThread::currentThreadId()
    肯定比单个
    std::cout
    慢。

结论:您对线程的调度没有任何硬性保证。然而,在正常操作中,两个线程平均获得几乎相同的 CPU 时间,因为操作系统调度程序没有理由偏向其中一个线程。使用调试器完全改变了这种正常行为。

© www.soinside.com 2019 - 2024. All rights reserved.