Qt篇: 多线程同步
多线程的本质
并发性是多线程编程的本质。何为并发性?指在同一计算机中,存在多个计算任务,这些计算任务具有同时执行的特性,这样能提高系统性能,程序响应速度更快。
- 在宏观上,所有线程并行执行;
- 多个线程相互独立,互不干涉,那事实真是这样吗?
常规问题解决方案
在平常的问题解决方案中,往往都是将同一个问题分解成若干个任务去解决,这些任务在执行解决上,又可以分为串行执行和并发执行,两者在效率上是很大不同,并发性效率可能是串行的几倍。下面以0+1+2+3+ ... + 1000求和为例,可以将这个求和分为三部分:任务1为0-300,、任务2为301-600和任务3为601-1000来解决这个问题。
串行执行及执行时间
#include <QCoreApplication>
#include <QThread>
#include <QTime>
#include <QDebug>
class SyncThread : public QThread
{
int m_begin_data;
int m_end_data;
int m_result;
public:
SyncThread(int begin, int end)
{
m_begin_data = begin;
m_end_data = end;
m_result = 0;
}
int getResult()
{
return m_result;
}
void work()
{
this->run();
}
protected:
void run()
{
qDebug() << objectName() << "run() begin...";
for( int i=m_begin_data; i<=m_end_data; i++ )
{
m_result += i;
msleep(10);
}
qDebug() << objectName() << "run() end...";
}
};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QTime timer;
timer.start();
qDebug() << "main begin...";
SyncThread s1(0, 300);
SyncThread s2(301, 600);
SyncThread s3(601, 1000);
s1.setObjectName("s1");
s2.setObjectName("s2");
s3.setObjectName("s3");
s1.work();
s2.work();
s3.work();
int result = s1.getResult() + s2.getResult() + s3.getResult();
qDebug() << "result: " << result;
qDebug() << "main end...";
qDebug() << timer.elapsed() << " ms";
return a.exec();
}
并发执行及执行时间
//s1.work();
//s2.work();
//s3.work();
// 在串行代码上只需要调用相应的线程启动函数即可
s1.start();
s2.start();
s3.start();
结果分析
- 现象:在计算耗时上,确实是缩短了好几倍,效率也提高上了,但是计算结果却是不准确的;
- 原因:多线程间并不是完全独立毫无依赖的,在某些特殊情况下,多线程执行在时序上存在依赖。在main函数中,相继调用了三个线程去处理各自任务,但是三个线程并没有完全执行完整,计算结果就出乎我们意料了,这就是同步问题。
同步的概念和解决方法
- 同步的概念:在特殊情况下,控制多线程间的相对执行顺序;
- 解决方法:QThread类直接提供了相关函数接口解决该问题,就是wait()方法,wait()停止当前线程的执行,等待目标线程的执行结束;
- 使用方法:按照下面的方式,依次给每条线程一个wait处理,即可得到正确的结果,且也证明耗时比串行的少,效率会比较高。
// 在串行代码上只需要调用相应的线程启动函数即可
s1.start();
s2.start();
s3.start();
s1.wait();
s2.wait();
s3.wait();