How to do it…

We will continue to use the code from the previous example project since we have already established a working program with multithreading:

  1. Open up myworker.h and add the following header:
#include <QObject>
#include <QDebug>
#include <QMutex>
  1. Then, we will add two new variables and make some changes to the class constructor:
public:
explicit MyWorker(QMutex *mutex);
int* myInputNumber;
QMutex* myMutex;

signals:
void showResults(int res);
void doneProcess();
  1. After that, open up myworker.cpp and change the class constructor to look like the following code. We no longer require the parent input since the object will not have a parent:
MyWorker::MyWorker(QMutex *mutex) {
myMutex = mutex;
}
  1. We will also change the process() function to look like this:
void MyWorker::process() {
myMutex->lock();
for (int i = 1; i < 100000; ++i){
*myInputNumber += i * i + 2 * i + 3 * i;
}
myMutex->unlock();
emit showResults(*myInputNumber);
emit doneProcess();
}
  1. Once you're done, open up mainwindow.cpp and make some changes to the code:
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) {
ui->setupUi(this);

int myNumber = 5;
QMutex* newMutex = new QMutex;

QThread* workerThread = new QThread;
QThread* workerThread2 = new QThread;
QThread* workerThread3 = new QThread;
MyWorker *workerObject = new MyWorker(newMutex);
MyWorker *workerObject2 = new MyWorker(newMutex);
MyWorker *workerObject3 = new MyWorker(newMutex);
  1. After that, we will set the myInputNumber variable of the worker object to myNumber. Note that we are referencing its pointer instead of the value:
workerObject->myInputNumber = &myNumber;
workerObject->moveToThread(workerThread);
connect(workerThread, &QThread::started, workerObject, &MyWorker::process);
connect(workerObject, &MyWorker::doneProcess, workerThread, &QThread::quit);
connect(workerObject, &MyWorker::doneProcess, workerObject, &MyWorker::deleteLater);
connect(workerObject, &MyWorker::showResults, this, &MainWindow::handleResults);
connect(workerThread, &QThread::finished, workerObject, &MyWorker::deleteLater);
  1. Repeat the previous step two more times for setting workerObject2, workerThread2, workerObject3, and workerThread3:
workerObject2->myInputNumber = &myNumber;
workerObject2->moveToThread(workerThread2);
connect(workerThread2, &QThread::started, workerObject2, &MyWorker::process);
connect(workerObject2, &MyWorker::doneProcess, workerThread2, &QThread::quit);
connect(workerObject2, &MyWorker::doneProcess, workerObject2, &MyWorker::deleteLater);
connect(workerObject2, &MyWorker::showResults, this, &MainWindow::handleResults);
connect(workerThread2, &QThread::finished, workerObject2, &MyWorker::deleteLater);

workerObject3->myInputNumber = &myNumber;
workerObject3->moveToThread(workerThread3);
connect(workerThread3, &QThread::started, workerObject3, &MyWorker::process);
connect(workerObject3, &MyWorker::doneProcess, workerThread3, &QThread::quit);
connect(workerObject3, &MyWorker::doneProcess, workerObject3, &MyWorker::deleteLater);
connect(workerObject3, &MyWorker::showResults, this, &MainWindow::handleResults);
connect(workerThread3, &QThread::finished, workerObject3, &MyWorker::deleteLater);
  1. Finally, we will start running those threads by calling start():
workerThread->start();
workerThread2->start();
workerThread3->start();
  1. If you build and run the program now, you should see a consistent result, no matter how many times you run it:
Final result: -553579035
Final result: -1107158075
Final result: -1660737115
  1. We are getting results every time we run the program because the mutex lock ensures that only one of the threads is able to modify the data while other threads await their completion. To see the difference without mutex locking, let's comment out the code:
void MyWorker::process() {
//myMutex->lock();

for (int i = 1; i < 100000; ++i) {
*myInputNumber += i * i + 2 * i + 3 * i;
}

//myMutex->unlock();

emit showResults(*myInputNumber);
emit doneProcess();
}

  1. Build and run the program again. This time, you will get a very different result when you run the program. For example, I've obtained the following results when running it on three occasions:
1st time:
Final result: -589341102
Final result: 403417142
Final result: -978935318

2nd time:
Final result: 699389030
Final result: -175723048
Final result: 1293365532

3rd time:
Final result: 1072831160
Final result: 472989964
Final result: -534842088
  1. This happens because the myNumber data is being manipulated by all the threads simultaneously in a random order, due to the nature of parallel computation. By locking the mutex, we make sure that the data can only be modified by a single thread and, hence, eliminated this issue.
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset