目录
2.1 简介
2.2 Qmutex 应用
2.3 QWaitCondition 应用
接下来继续说线程同步的问题,当n个线程在一起运行时,为了控制其先后运行顺序,或者 对共享数据的访问 ,这就需要用到线程的功能,这仅是我能想到的两个情形.
QT 提供 了QMutex, QReadWriteLock, QSemaphore QWaitCondition 用以提供线程同步.这里就选用QMutex,QWaitCondition 结合一个 “下载工具” 例子 分别讲解说明,其他的以后需用到再说. 如果一篇文章全部讲完,实在够呛,能力有限
2.1 Qmutex 应用
首先我们将使用 QMutex来实现 下载工具 中的 “下载/暂停/停止”三种下载状态切换,以下简称为状态切换。
简单说一下Qmutex,该类是用来同步线程最基础的类。一般通过调用lock /unlock方法.使用Qmutex就是像检测一个标志一样,如果不是true就继续等待,只不过这个等待的过程不会占用cpu时间片。这和循环检测每个标志位有明显的不同。
使用QMutext需要注意的两点是:
1.在同一线程中,Qmutex 不能重复lock或unlock,换句话说就是lock/unlock 只能成对出现。幸好的是如果你不小心这么做的时候,debug时有所提示.
2.线程lock后,只能在同一个线程中进行unlock,例如,A线程lock后,如果企图在B线程直接unlock 来释放,这将会引发错误。
上回讲到线程的控制提到sleep是无法休眠到一半然后唤醒的. 使用Qmutex 可以改变 sleep完全没有回应的局面。在这里我们需要用一个变量做开关,使用Qmutex 做同步访问以达到一种唤醒的效果,也就是我们要做的状态切换了,只不过说法不同。
想象一下该下载工具,为了ui的响应,一般运行时有两个线程.一个是main线程用于gui,另一个是worker线程,用于下载数据,用户随时决定要进行状态切换.
下面是关键的代码部分
#include <QThread>
#include <QMutex>
class CThread : public QThread
{
public:
CThread();
~CThread();
public:
enum E_downloadState{DS_INIT,DS_START, DS_PAUSE, DS_STOP};
void startDownload();
void pauseDownload();
void stopDownload();
E_downloadState downState() const;
protect:
void run();
private:
QMutex mDownloadMutex;
E_downloadState mState; //用于mutex的变量
void setDownloadMutex(bool lock);
void setDownState( E_downloadState state);
};
画个示意图
开始下载:
暂停下载
中止下载
在这里为了看清整个控制过程,我用qDebug()模拟出下载工具的状态切换