【问题标题】:QMutex with QThread - prime number sekeerQMutex 与 QThread - 素数搜索器
【发布时间】:2019-08-11 17:05:32
【问题描述】:

您好,我在使用 qmutex 掌握 qthread 时遇到问题 - 通常如何使用它 - 学习它我正在尝试创建限制为 8,000,000 的素数搜索器,但即使我使用给定的代码作为基础,我也失败了有类似的例子 - 我真的不知道我误解了什么,但我创建了一个全局变量并将它传递给两个线程 - 在给定的代码中,一个线程正在递增变量,第二个线程正在计算 - 但是这不是一个好的解决方案 - 从长远来看 - 代码最多可以工作 8000 所以说我不确定我是否做对了。文档只让我了解如何做到这一点 - 代码示例不是很有帮助。

我试过了: - 以代码示例为基础运行它 - 在主线程中创建一个循环是什么破坏了程序 - 过滤两个线程不会冲突的数字

以下是实际代码: 计算对象.h

#include <QObject>
#include <QThread>

class CalculateObject : public QThread
{
    Q_OBJECT
public:
    CalculateObject(QMutex *mu, int *nu);
    void run();
    bool isPrime(unsigned int);
    QMutex *mutex;
    int *counter;
    bool checker;
    QString name;
signals:
    void sendResult(int);
    void done();
};

计算object.cpp

#include "calculateobject.h"
#include <QtMath>


const int LIMIT = 8000000;

CalculateObject::CalculateObject(QMutex *mu, int *nu)
{
    counter = nu;
    mutex = mu;
    checker = false;
}
bool CalculateObject::isPrime(unsigned int number)
{
    if(number > 3)
    {
        if (number % 2 == 0)
        {
            return false;
        }
        const unsigned int MAX = (unsigned int)sqrt(number) + 1;
        for (int i = 3;i < MAX; i += 2) {
            if((number % i) == 0)
            {
                return false;
            }
        }
       return true;
    }
    if(number < 2)
    {
        return false;
    }
    return true;
}
void CalculateObject::run()
{
    int result = 0;
    while(*counter < 8000)
    {
        QThread::usleep(5);
        if(this->name == "first")
        {
            mutex->lock();
            *counter += 1;
            qDebug() << *counter;
            mutex->unlock();
        }
        else {
            mutex->lock();
            checker = isPrime(*counter);
            mutex->unlock();
            if(checker == true)
            {
                result = 1;
                emit(sendResult(result));
            }

        }
    }
        emit(done());
}

计算器小部件.h

#include <QWidget>
#include <QPushButton>
#include <QLabel>
#include "calculateobject.h"
#include <QThread>

class CalculatorWidget : public QWidget
{
    Q_OBJECT

public:
    explicit CalculatorWidget(QWidget *parent = nullptr);
    ~CalculatorWidget();
    CalculateObject *object, *object2;
public slots:
    void readResults(int counter);
    void startThread();
    void finishThread();
    void endMessage();
    void controller();
private:
    int reader;
    Ui::CalculatorWidget *ui;
    QPushButton *start;
    QLabel *resultReader;
    QThread *newProcess;
    QThread *newerProcess;
signals:
    void end();

};

calculatorwidget.cpp

#include "calculatorwidget.h"
#include "ui_calculatorwidget.h"
#include <QMessageBox>

int number = 0;
QMutex aMutex;

CalculatorWidget::CalculatorWidget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::CalculatorWidget)
{
    ui->setupUi(this);
    start = ui->start;
    resultReader = ui->result;
    newProcess = new QThread;
    newerProcess = new QThread;
    reader = 0;
    connect(start, &QPushButton::clicked, this, &CalculatorWidget::startThread);
}
void CalculatorWidget::controller()
{
    static int control = 0;
    control++;
    if(control == 2)
    {
        emit(end());
    }
}

CalculatorWidget::~CalculatorWidget()
{
    delete ui;
}
void CalculatorWidget::readResults(int counter)
{
    reader += counter;
}
void CalculatorWidget::startThread()
{
    int *count = &number;
    QMutex *mutex = &aMutex;
    object = new CalculateObject(mutex, count);
    object2 = new CalculateObject(mutex, count);
    connect(object, &CalculateObject::sendResult, this, &CalculatorWidget::readResults);
    connect(object2, &CalculateObject::sendResult, this, &CalculatorWidget::readResults);
    connect(object, &CalculateObject::done, this, &CalculatorWidget::controller);
    connect(object2, &CalculateObject::done, this, &CalculatorWidget::controller);
    connect(this, &CalculatorWidget::end, this, &CalculatorWidget::finishThread);
    object->name = "first";
    object2->name = "second";
    object->start();
    object2->start();

}
void CalculatorWidget::finishThread()
{
    newProcess->exit();
    newProcess->wait(3);
    newerProcess->wait(3);
    newerProcess->exit();
    endMessage();
}
void CalculatorWidget::endMessage()
{
    QMessageBox msg;
    msg.setText("The calculation Process is done" + QString::number(reader));
    msg.exec();
}

main.cpp

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    CalculatorWidget widget;
    widget.show();
    return a.exec();
}


用户界面文件

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>CalculatorWidget</class>
 <widget class="QWidget" name="CalculatorWidget">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>400</width>
    <height>300</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>Form</string>
  </property>
  <layout class="QVBoxLayout" name="verticalLayout_2">
   <item>
    <layout class="QVBoxLayout" name="verticalLayout">
     <item>
      <widget class="QLabel" name="label">
       <property name="text">
        <string>This program calculates how many prime numbers </string>
       </property>
      </widget>
     </item>
     <item>
      <widget class="QLabel" name="label_2">
       <property name="text">
        <string>are in de spectrum from 0 to 8000000</string>
       </property>
      </widget>
     </item>
    </layout>
   </item>
   <item>
    <layout class="QHBoxLayout" name="horizontalLayout">
     <item>
      <widget class="QPushButton" name="start">
       <property name="text">
        <string>Start</string>
       </property>
      </widget>
     </item>
     <item>
      <widget class="QLabel" name="result">
       <property name="text">
        <string/>
       </property>
      </widget>
     </item>
    </layout>
   </item>
  </layout>
 </widget>
 <resources/>
 <connections/>
</ui>

我希望我的代码会显示从 0 到 8,000,000 的频谱中有多少个质数,但程序正在运行或崩溃

【问题讨论】:

  • 请发布一个完整的最小可复制示例。我只是无法编译你的程序。缺少包含,更糟糕的是缺少 Ui 文件。我还认为,您的程序远非最小。尽可能多地删除仍然具有相同行为的行为。您还应该考虑使用QMutexLocker 以使您的代码不易出错且更易于理解。
  • 文件包含在轮毂标题中
  • 扩展 QThread 通常是不好的做法。查看此页面wiki.qt.io/QThreads_general_usage 以获取示例。使用这种方法,在大多数情况下您不需要互斥体。

标签: c++ qt qt5 c++14


【解决方案1】:

我真的不知道,你真正的问题是什么,但你应该尝试在run() 函数的开头使用QMutexLocker。试试你的程序是否安全运行。

您还应该记住,读取共享变量也必须受到互斥锁的保护。另见帖子QMutex needed to read variable

void CalculateObject::run()
{
    QMutexLocker lock(mutex);
    int result = 0;
    while(*counter < 8000)
    {
        //QThread::usleep(5);
        if(this->name == "first")
        {
            *counter += 1;
            qDebug() << *counter;
        }
        else {
            checker = isPrime(*counter);
            if(checker == true)
            {
                result = 1;
                emit(sendResult(result));
            }

        }
    }
    emit(done());
}

如果这解决了您的问题,请报告。

【讨论】:

  • 感谢 Aleph0 抽出宝贵时间 - 您的解决方案运行良好 - 我没有考虑 qMutexLocker - 这是您自学的时候。多谢。
猜你喜欢
  • 1970-01-01
  • 2013-12-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-27
  • 2017-10-03
  • 2011-06-06
  • 2022-01-24
相关资源
最近更新 更多